using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AbpEfCore
{
public class JoinResult<TLeft, TRight>
{
public TLeft Left { get; set; }
public TRight Right { get; set; }
}
public static class QueryLinqHelper
{
public static IQueryable<TResult> InnerJoin<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IQueryable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector)
{
return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector);
}
public static IQueryable<JoinResult<TOuter, TInner>> InnerJoin<TOuter, TInner, TKey>(
this IQueryable<TOuter> outer,
IQueryable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector
)
{
return outer.Join(inner, outerKeySelector, innerKeySelector, (x, y) => new JoinResult<TOuter, TInner> { Left = x, Right = y });
}
public static IQueryable<JoinResult<TLeft, TRight>> LeftJoin<TLeft, TRight, TKey>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector
)
{
return leftItems.GroupJoin(rightItems, leftKeySelector, rightKeySelector, (left, rightg) => new { left, rightg })
.SelectMany(r => r.rightg.DefaultIfEmpty()
, (x, y) => new JoinResult<TLeft, TRight> { Left = x.left, Right = y });
}
public static IQueryable<JoinResult<TLeft, TRight>> LeftExcludingJoin<TLeft, TRight, TKey>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector
)
{
return leftItems.GroupJoin(rightItems, leftKeySelector, rightKeySelector, (left, rightg) => new { left, rightg })
.SelectMany(r => r.rightg.DefaultIfEmpty()
, (x, y) => new JoinResult<TLeft, TRight> { Left = x.left, Right = y }).Where(z => z.Right.Equals(null));
}
public static IQueryable<JoinResult<TLeft, TRight>> RightJoin<TLeft, TRight, TKey>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector
)
{
return rightItems.GroupJoin(leftItems, rightKeySelector, leftKeySelector, (right, leftg) => new { leftg, right })
.SelectMany(l => l.leftg.DefaultIfEmpty(),
(x, y) => new JoinResult<TLeft, TRight> { Left = y, Right = x.right });
}
public static IQueryable<JoinResult<TLeft, TRight>> RightExcludingJoin<TLeft, TRight, TKey>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector
)
{
return rightItems.GroupJoin(leftItems, rightKeySelector, leftKeySelector, (right, leftg) => new { leftg, right })
.SelectMany(l => l.leftg.DefaultIfEmpty(),
(x, y) => new JoinResult<TLeft, TRight> { Left = y, Right = x.right })
.Where(z => z.Left.Equals(null))
;
}
public static IQueryable<JoinResult<TLeft, TRight>> FullJoin<TLeft, TRight, TKey>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector
)
{
return leftItems.LeftJoin(rightItems, leftKeySelector, rightKeySelector).Concat(leftItems.RightExcludingJoin(rightItems, leftKeySelector, rightKeySelector));
}
}
public class Program
{
public static void Main(string[] args)
{
using (var db = new MyContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
var tmp_a=new A[]{
new A{Id=1,a="a0",a1="a1",forkey="a"},
new A{Id=3,a="a2",a1="a1",forkey="d"},
};
var tmp_b=new B[]{
new B{Id=1,b="b0",b1="b1",forkey="a"},
new B{Id=3,b="b2",b1="b1",forkey="c"},
};
db.A.AddRange(tmp_a);
db.B.AddRange(tmp_b);
db.SaveChanges();
}
using (var db = new MyContext())
{
// Run queries
var query = db.A.FullJoin(db.B,x=>x.forkey,y=>y.forkey).ToList();
}
Console.WriteLine("Program finished.");
}
}
public class MyContext : DbContext
{
private static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b =>
{
b
.AddConsole()
.AddFilter("", LogLevel.Debug);
});
public DbSet<A> A{ get; set; }
public DbSet<B> B{ get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Select 1 provider
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=_ModelApp;Trusted_Connection=True;Connect Timeout=5;ConnectRetryCount=0")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure model
}
}
public class A
{
public int Id { get; set; }
public string a { get; set; }
public string a1 { get; set; }
public string forkey {get;set;}
}
public class B
{
public int Id { get; set; }
public string b { get; set; }
public string b1 { get; set; }
public string forkey {get;set;}
}
}
Throw:
System.InvalidOperationException:“Unable to track an entity of type 'A' because primary key property 'Id' is null.”
@LostAsk When I run this code I get the following exception, which makes sense given the model defined and the way it is used. It is not the exception you are reporting.
Unhandled exception. Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert explicit value for identity column in table 'A' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'B' when IDENTITY_INSERT is set to OFF.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()
at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method)
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
ClientConnectionId:e465a788-cf67-4f68-8c21-688c204d4bc1
Error Number:544,State:1,Class:16
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at AbpEfCore.Program.Main(String[] args) in
@ajcvickers
sorry!
Code:
public static void Main(string[] args)
{
using (var db = new MyContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
var tmp_a = new A[]{
new A{a="a0",a1="a1",forkey="a"},
new A{a="a2",a1="a1",forkey="d"},
};
var tmp_b = new B[]{
new B{b="b0",b1="b1",forkey="a"},
new B{b="b2",b1="b1",forkey="c"},
};
db.A.AddRange(tmp_a);
db.B.AddRange(tmp_b);
db.SaveChanges();
}
using (var db = new MyContext())
{
// Run queries
var query = db.A.FullJoin(db.B, x => x.forkey, y => y.forkey).ToList();
}
Console.WriteLine("Program finished.");
}
The query results in creation of entity instances which will then be tracked. However, if any of those instances are null then we are still trying to track them when we should not.
@LostAsk Using AsNoTracking() on the query allowed me to get the results. As a workaround you could manually tack the entities afterwards if you need tracking.
Results look like:

Simplified repro:
```C#
namespace AbpEfCore
{
public class JoinResult
{
public TLeft Left { get; set; }
public TRight Right { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
using (var db = new MyContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
var tmp_a = new A[]
{
new A {a = "a0", a1 = "a1", forkey = "a"},
new A {a = "a2", a1 = "a1", forkey = "d"},
};
var tmp_b = new B[]
{
new B {b = "b0", b1 = "b1", forkey = "a"},
new B {b = "b2", b1 = "b1", forkey = "c"},
};
db.A.AddRange(tmp_a);
db.B.AddRange(tmp_b);
db.SaveChanges();
}
using (var db = new MyContext())
{
// Run queries
Expression<Func<A, string>> leftKeySelector = x => x.forkey;
Expression<Func<B, string>> rightKeySelector = y => y.forkey;
var query = db.A.AsNoTracking().GroupJoin(
db.B,
leftKeySelector,
rightKeySelector,
(left, rightg) => new
{
left,
rightg
})
.SelectMany(
r => r.rightg.DefaultIfEmpty(),
(x, y) => new JoinResult<A, B>
{
Left = x.left,
Right = y
})
.Concat(
db.B.GroupJoin(
db.A,
rightKeySelector,
leftKeySelector,
(right, leftg) => new {leftg, right})
.SelectMany(l => l.leftg.DefaultIfEmpty(),
(x, y) => new JoinResult<A, B>
{
Left = y,
Right = x.right
})
.Where(z => z.Left.Equals(null)))
.ToList();
}
}
}
public class MyContext : DbContext
{
private static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b =>
{
b
.AddConsole()
.AddFilter("", LogLevel.Debug);
});
public DbSet<A> A { get; set; }
public DbSet<B> B { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Select 1 provider
optionsBuilder
.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=_ModelApp;Trusted_Connection=True;Connect Timeout=5;ConnectRetryCount=0")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure model
}
}
public class A
{
public int Id { get; set; }
public string a { get; set; }
public string a1 { get; set; }
public string forkey { get; set; }
}
public class B
{
public int Id { get; set; }
public string b { get; set; }
public string b1 { get; set; }
public string forkey { get; set; }
}
}
```
Set operation did not assign proper nullability to entity shaper.
OK! Thanks!
@ajcvickers @smitpatel
I refer to other people's query helper and modify it myself
ref:https://www.codenong.com/5489987/
the ef6 and EF core 2 operate normally, but EF core 3 reports an error
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AbpEfCore
{
public static class QueryLinqHelper
{
public static IQueryable<TResult> InnerJoin<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IQueryable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector)
{
return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector);
}
//private static Expression<Func<TP, TC, TResult>> CastSMBody<TP, TC, TResult>(LambdaExpression ex, TP unusedP, TC unusedC, TResult unusedRes) => (Expression<Func<TP, TC, TResult>>)ex;
public static IQueryable<TResult> LeftJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) where TLeft : class where TRight : class where TResult : class
{
Expression<Func<TP, TC, TResult1>> CastSMBody<TP, TC, TResult1>(LambdaExpression ex, TP unusedP, TC unusedC, TResult1 unusedRes) => (Expression<Func<TP, TC, TResult1>>)ex;
// (lrg,r) => resultSelector(lrg.left, r)
var sampleAnonLR = new { left = (TLeft)null, rightg = (IEnumerable<TRight>)null };
var parmP = Expression.Parameter(sampleAnonLR.GetType(), "lrg");
var parmC = Expression.Parameter(typeof(TRight), "r");
var argLeft = Expression.PropertyOrField(parmP, "left");
var newleftrs = CastSMBody(Expression.Lambda(resultSelector.Apply(argLeft, parmC), parmP, parmC), sampleAnonLR, (TRight)null, (TResult)null);
return leftItems.GroupJoin(rightItems, leftKeySelector, rightKeySelector, (left, rightg) => new { left, rightg }).SelectMany(r => r.rightg.DefaultIfEmpty(), newleftrs);
}
public static IQueryable<TResult> LeftExcludingJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) where TLeft : class where TRight : class where TResult : class
{
Expression<Func<TParm, TResult1>> CastSBody<TParm, TResult1>(LambdaExpression ex, TParm unusedP, TResult1 unusedRes)
{
return (Expression<Func<TParm, TResult1>>)ex;
}
var sampleAnonLR = new { leftg = (TLeft)null, right = (TRight)null };
var parmLgR = Expression.Parameter(sampleAnonLR.GetType(), "lrg");
var argLeft = Expression.Constant(null, typeof(TRight));
var argRight = Expression.PropertyOrField(parmLgR, "leftg");
var newrightrs = CastSBody(Expression.Lambda(resultSelector.Apply(argRight, argLeft), parmLgR), sampleAnonLR, (TResult)null);
return leftItems.GroupJoin(rightItems, leftKeySelector, rightKeySelector, (leftg, right) => new { leftg, right })
.SelectMany(r => r.right.DefaultIfEmpty(), (leftg, right) => new { leftg.leftg, right })
.Where(lrg => lrg.right==null).Select(newrightrs);
}
public static IQueryable<TResult> RightJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) where TLeft : class where TRight : class where TResult : class
{
Expression<Func<TP, TC, TResult1>> CastSMBody<TP, TC, TResult1>(LambdaExpression ex, TP unusedP, TC unusedC, TResult1 unusedRes) => (Expression<Func<TP, TC, TResult1>>)ex;
// (lgr,l) => resultSelector(l, lgr.right)
var sampleAnonLR = new { leftg = (IEnumerable<TLeft>)null, right = (TRight)null };
var parmP = Expression.Parameter(sampleAnonLR.GetType(), "lgr");
var parmC = Expression.Parameter(typeof(TLeft), "l");
var argRight = Expression.PropertyOrField(parmP, "right");
var newrightrs = CastSMBody(Expression.Lambda(resultSelector.Apply(parmC, argRight), parmP, parmC), sampleAnonLR, (TLeft)null, (TResult)null);
return rightItems.GroupJoin(leftItems, rightKeySelector, leftKeySelector, (right, leftg) => new { leftg, right })
.SelectMany(l => l.leftg.DefaultIfEmpty(), newrightrs);
}
public static IQueryable<TResult> RightExcludingJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) where TLeft : class where TRight : class where TResult : class
{
Expression<Func<TParm, TResult1>> CastSBody<TParm, TResult1>(LambdaExpression ex, TParm unusedP, TResult1 unusedRes) => (Expression<Func<TParm, TResult1>>)ex;
// newrightrs = lgr => resultSelector((TLeft)null, lgr.right)
var sampleAnonLgR = new { leftg = (TLeft)null, right = (TRight)null };
var parmLgR = Expression.Parameter(sampleAnonLgR.GetType(), "lgr");
var argLeft = Expression.Constant(null, typeof(TLeft));
var argRight = Expression.PropertyOrField(parmLgR, "right");
var newrightrs = CastSBody(Expression.Lambda(resultSelector.Apply(argLeft, argRight), parmLgR), sampleAnonLgR, (TResult)null);
return rightItems.GroupJoin(leftItems, rightKeySelector, leftKeySelector, (right, leftg) => new { leftg, right })
.SelectMany(l => l.leftg.DefaultIfEmpty(), (right, leftg) => new { leftg, right.right })
.Where(lgr => lgr.leftg==null)
.Select(newrightrs);
}
public static IQueryable<TResult> FullJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) where TLeft : class where TRight : class where TResult : class
{
var left = leftItems.LeftJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector);
var right = leftItems.RightExcludingJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector);
var all= left.Concat(right);
return all;
}
public static Expression Apply(this LambdaExpression e, params Expression[] args)
{
var b = e.Body;
foreach (var pa in e.Parameters.Cast<ParameterExpression>().Zip(args, (p, a) => new { p, a }))
{
b = b.Replace(pa.p, pa.a);
}
return b.PropagateNull();
}
public static Expression Replace(this Expression orig, Expression from, Expression to) => new ReplaceVisitor(from, to).Visit(orig);
public class ReplaceVisitor : System.Linq.Expressions.ExpressionVisitor
{
public readonly Expression from;
public readonly Expression to;
public ReplaceVisitor(Expression _from, Expression _to)
{
from = _from;
to = _to;
}
public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
public static Expression PropagateNull(this Expression orig) => new NullVisitor().Visit(orig);
public class NullVisitor : System.Linq.Expressions.ExpressionVisitor
{
public override Expression Visit(Expression node)
{
if (node is MemberExpression nme && nme.Expression is ConstantExpression nce && nce.Value == null)
return Expression.Constant(null, nce.Type.GetMember(nme.Member.Name).Single().GetMemberType());
else
return base.Visit(node);
}
}
public static Type GetMemberType(this MemberInfo member)
{
return member switch
{
FieldInfo mfi => mfi.FieldType,
PropertyInfo mpi => mpi.PropertyType,
EventInfo mei => mei.EventHandlerType,
_ => throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", nameof(member)),
};
//switch (member)
//{
// case FieldInfo mfi: return mfi.FieldType;
// case PropertyInfo mpi: return mpi.PropertyType;
// case EventInfo mei: return mei.EventHandlerType;
// default: throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", nameof(member));
//}
}
}
public class Program
{
public static void Main(string[] args)
{
using (var db = new MyContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
var tmp_a = new A[]
{
new A {a = "a0", a1 = "a1", forkey = "a"},
new A {a = "a2", a1 = "a1", forkey = "d"},
};
var tmp_b = new B[]
{
new B {b = "b0", b1 = "b1", forkey = "a"},
new B {b = "b2", b1 = "b1", forkey = "c"},
};
db.A.AddRange(tmp_a);
db.B.AddRange(tmp_b);
db.SaveChanges();
}
using (var db = new MyContext())
{
var query=db.A.AsNoTracking().FullJoin(db.B, (x)=>x.forkey, (y)=>y.forkey, (u, v) => new { left=u,right=v }).ToList();
}
}
}
public class MyContext : DbContext
{
private static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b =>
{
b
.AddConsole()
.AddFilter("", LogLevel.Debug);
});
public DbSet<A> A { get; set; }
public DbSet<B> B { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Select 1 provider
optionsBuilder
.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=_ModelApp;Trusted_Connection=True;Connect Timeout=5;ConnectRetryCount=0")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure model
}
}
public class A
{
public int Id { get; set; }
public string a { get; set; }
public string a1 { get; set; }
public string forkey { get; set; }
}
public class B
{
public int Id { get; set; }
public string b { get; set; }
public string b1 { get; set; }
public string forkey { get; set; }
}
}
Throw Exception:
System.InvalidOperationException:When performing a set operation, both operands must have the same Include operations.”
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessSetOperation(NavigationExpansionExpression outerSource, MethodInfo genericMethod, NavigationExpansionExpression innerSource)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)