昨天EF莫名其妙的,掉所有接口访问都出现如下错误:百度,Google了半天,倒是有很多人都遇到了这个问题,但都没有一个解决方案,或者解决方案无效。通过层层排除,终于找到问题的所在。记录下来,给以后再遇到此问题的朋友们节省一些找问题的时间。而且这错误的原因如果不细心还真不好找。
异常信息如下:
{"Message":"出现错误。","ExceptionMessage":"值不能为 null。\r\n参数名: entitySet","ExceptionType":"System.ArgumentNullException","StackTrace":" 在 System.Data.Entity.Utilities.Check.NotNull[T](T value, String parameterName)\r\n 在 System.Data.Entity.Core.Mapping.EntitySetMapping..ctor(EntitySet entitySet, EntityContainerMapping containerMapping)\r\n 在 System.Data.Entity.ModelConfiguration.Edm.DbDatabaseMappingExtensions.AddEntitySetMapping(DbDatabaseMapping databaseMapping, EntitySet entitySet)\r\n 在 System.Data.Entity.ModelConfiguration.Edm.Services.TableMappingGenerator.Generate(EntityType entityType, DbDatabaseMapping databaseMapping)\r\n 在 System.Data.Entity.ModelConfiguration.Edm.Services.DatabaseMappingGenerator.GenerateEntityTypes(DbDatabaseMapping databaseMapping)\r\n 在 System.Data.Entity.ModelConfiguration.Edm.Services.DatabaseMappingGenerator.Generate(EdmModel conceptualModel)\r\n 在 System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.GenerateDatabaseMapping(EdmModel model, DbProviderInfo providerInfo, DbProviderManifest providerManifest)\r\n 在 System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)\r\n 在 System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)\r\n 在 System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)\r\n 在 System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)\r\n 在 System.Data.Entity.Internal.LazyInternalContext.InitializeContext()\r\n 在 System.Data.Entity.Internal.InternalContext.Initialize()\r\n 在 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)\r\n 在 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()\r\n 在 System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()\r\n 在 System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()\r\n 在 System.Data.Entity.QueryableExtensions.SingleOrDefaultAsync[TSource](IQueryable`1 source, Expression`1 predicate, CancellationToken cancellationToken)\r\n 在 System.Data.Entity.QueryableExtensions.SingleOrDefaultAsync[TSource](IQueryable`1 source, Expression`1 predicate)\r\n 在 BellChat.Business.UserService.<Login>d__4.MoveNext()
值不能为 null。参数名: entitySet。 表明是因为DBmodel 和数据库表格映射过程出现的问题,可以从model和表字段对应不上,或者数据库字段类型EF无法识别,这两点着手寻找错误的根源。
我这边最后找到的原因如下:
我有一处Include代码:
var result = db.Conversations.Where(m => (m.UserId == user.Id || m.TargetUserId == user.Id) && m.Id > req.Begin)
.Include(m => m.TargetUser).Include(m => m.LastMsg).Take(req.Count);
其中的TargetUser对象并不是对应数据库中的user表DBModel,而是一个自定义的responseModel。导致EF的Include失败,而这种错误完全不影响编译,调试时也无法定位到Include(m => m.TargetUser)这句代码,且该错误不仅仅只影响这一处接口调用的结果,它会导致整个EF数据库操作都报错,让你摸不着头脑。就感觉是EF在系统启动的时候先阅读整个程序代码,提前映射所有model,只要有一个model映射不上,整个EF就不能用。
解决办法如下:
将.Include(m => m.TargetUser)中的TargetUser改成数据库model就好了
public partial class Conversation
{
[JsonIgnore]
public User TargetUser { get; set; } //原来是public SeekerSimple TargetUser { get; set; }
public Message LastMsg { get; set; }
}