实体类型 不是当前背景模型的一部分

问题描述 投票:117回答:13

我正在进入实体框架,但我不确定我是否错过了代码优先方法中的关键点。

我正在使用基于https://genericunitofworkandrepositories.codeplex.com/代码的通用存储库模式并创建了我的实体。

但是当我尝试访问或修改实体时,我会遇到以下情况:

System.InvalidOperationException:实体类型Estate不是当前上下文的模型的一部分。

当我尝试从我的存储库访问它时会发生这种情况:

public virtual void Insert(TEntity entity)
{
    ((IObjectState)entity).ObjectState = ObjectState.Added;
    _dbSet.Attach(entity); // <-- The error occurs here
    _context.SyncObjectState(entity);
}

数据库(./SQLEXPRESS)创建得很好,但实体(表)不是在启动时创建的。

我想知道我是否需要显式设置实体的映射? EF不能自己做到这一点吗?

我的实体是:

public class Estate : EntityBase
{
    public int EstateId { get; set; }
    public string Name { get; set; }
} 

我的背景如下:

public partial class DimensionWebDbContext : DbContextBase // DbContextBase inherits DbContext
{
    public DimensionWebDbContext() :
        base("DimensionWebContext")
    {
        Database.SetInitializer<DimensionWebDbContext>(new CreateDatabaseIfNotExists<DimensionWebDbContext>());
        Configuration.ProxyCreationEnabled = false;
    }

    public new IDbSet<T> Set<T>() where T : class
    {
        return base.Set<T>();
    }

}

是否有任何特定原因导致此错误发生?我已尝试启用迁移并启用自动迁移,而无需任何帮助。

c# entity-framework ef-code-first dbcontext
13个回答
125
投票

把它放在你的自定义DbContext类中:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Estate>().ToTable("Estate");
}

如果您的表未在启动时创建,这就是原因。您需要在OnModelCreating方法覆盖中告诉DbContext有关它们的信息。

您可以在此处执行自定义的每实体映射,也可以将它们分成单独的EntityTypeConfiguration<T>类。


1
投票

如果您使用由于某种原因而过时的持久模型缓存,也会发生这种情况。如果您的上下文已缓存到文件系统上的EDMX文件(通过DbConfiguration.SetModelStore),则将永远不会调用OnModelCreating,因为将使用缓存版本。因此,如果您的缓存存储中缺少某个实体,那么即使连接字符串正确,您也会收到上述错误,该表存在于数据库中,并且该实体已在DbContext中正确设置。


0
投票

听起来很明显,但请确保您没有明确忽略该类型:

modelBuilder.Ignore<MyType>();


0
投票

添加到配置中的实体(甚至是空实体)的映射将导致实体类型成为上下文的一部分。我们有一个与使用空地图修复的其他实体没有任何关系的实体。


0
投票

如果你先尝试数据库,那么请确保你的表有主键


0
投票

Visual Studio 2019似乎对我有用。我通过在2017年再次生成edmx模型来修复它。


65
投票

显然,这个错误非常通用,可能有很多原因。在我的例子中,它是如下:.edmx生成的连接字符串(在Web.config中)无效。经过近一天的尝试,我将连接字符串从EF字符串更改为ADO.NET字符串。这解决了我的问题。

例如,EF字符串看起来像这样:

<connectionStrings> 
  <add name="BlogContext"  
    connectionString="metadata=res://*/BloggingModel.csdl| 
                               res://*/BloggingModel.ssdl| 
                               res://*/BloggingModel.msl; 
                               provider=System.Data.SqlClient 
                               provider connection string= 
                               &quot;data source=(localdb)\v11.0; 
                               initial catalog=Blogging;
                               integrated security=True; 
                               multipleactiveresultsets=True;&quot;" 
     providerName="System.Data.EntityClient" /> 
</connectionStrings>

ADO.NET字符串如下所示:

<connectionStrings>
  <add name="BlogContext"  
        providerName="System.Data.SqlClient"  
        connectionString="Server=.\SQLEXPRESS;Database=Blogging;
        Integrated Security=True;"/> 
</connectionStrings>

资料来源:http://msdn.microsoft.com/nl-nl/data/jj556606.aspx


11
投票

对我来说,问题是我没有在实体框架的上下文中包含我的数据库集中的实体类。

public DbSet<ModelName> ModelName { get; set; }

8
投票

问题可能出在连接字符串中。确保您的连接字符串适用于SqlClient提供程序,没有与EntityFramework相关的元数据内容。


8
投票

您可以尝试从模型中删除表并再次添加。您可以通过从解决方案资源管理器中打开.edmx文件来直观地执行此操作。

脚步:

  1. 双击解决方案资源管理器中的.edmx文件
  2. 右键单击要删除的表头,然后选择“从模型中删除”
  3. 现在再次右键单击工作区并选择“从数据库更新模型”。
  4. 从表格列表中再次添加表格
  5. 清理并构建解决方案

3
投票

当数据库中的现有表未正确映射到代码优先模型时,我已经看到此错误。具体来说,我在数据库表中有一个char(1),在C#中有一个char。将模型更改为字符串解决了问题。


2
投票

用连接字符串检查另一件事 - 模型名称。我首先使用了两个实体模型,DB。在配置中,我复制了一个实体连接,重命名了它,并更改了连接字符串部分。我没有改变的是模型名称,所以当实体模型正确生成时,当启动上下文时,EF正在查找实体的错误模型。

看起来很明显写下来,但有四个小时我不会回来。


2
投票

通过更新连接字符串的元数据部分解决了我的问题。显然它指的是错误的.c​​sdl / .ssdl / .msl引用。


1
投票

对我来说,问题是我使用了connection string模型(.edmx)生成的ADO.Net。更改连接字符串解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.