实体类型<type>不是当前上下文模型的一部分


146

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

我正在使用基于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>();
    }

}

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

Answers:


142

将其放在您的自定义DbContext类中:

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

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

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


1
谢谢,丹-这已解决。现在,表已创建。没有别的办法了,EF不能独自做到这一点吗?我不能只用[ToTable('Estates')]或类似名称注释实体?
janhartmann

3
我认为,OnModelCreating如果您的实体与您的实体在同一程序集中,则可以在不重写的情况下工作DbContext。不过,我从未使用过实体的数据注释,因此无法确定。您始终可以扫描自己中的部件OnModelCreating以查找其他部件中的实体并自动注册它们(这是Tripod所做的)。
danludwig 2013年

嗯当然了 感谢您提供有关三脚架操作方法的注释,我现在已经做过类似的事情,而且看起来工作还不错。(也感谢您在github.com/danludwig/Layout3/blob/master/UCosmic.Domain/Api/…上的反射扩展)。现在,我只需要它查找引用程序集,而不是查找GetType()程序集。“ var assembly = Assembly.Load(” Dimension.Web.Domain“);” 不太漂亮;-)
janhartmann

或者,也许只是将新的/ Mapping /文件夹移至Impl项目而不是Domain中。
janhartmann

@meep或danludwig。能否请您告诉我更多有关三脚架的信息或分享给我。
DkAngelito 2014年

73

显然,此错误非常笼统,可能有多种原因。在我的情况下,情况如下:生成的连接字符串(在Web.config中).edmx无效。经过几乎一天的尝试,我将连接字符串从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


17
我的问题还在于连接字符串。我重命名了数据模型并重新运行了t4模板,但是忘记了更新连接字符串中的元数据(.csdl,.ssdl,.msl文件)。您的回答使我意识到了这一点,谢谢!
Vyskol 2014年

4
如果使用身份模型进行身份验证,则需要2个连接字符串:一个,可以重命名或不重命名的“ DefaultConnection”,并放入公共ApplicationDbContext()中:base(“ IdentityDbContext”,throwIfV1Schema:false){}这就是触发我的错误的原因就像你的一样(我那里有EF字符串)。第二个连接字符串是使用向导添加EF生成的,它要求输入连接字符串参数。我希望这可以帮助别人。
JustJohn

同样在这里。令人难以置信的令人沮丧
Nick Molyneux

1
我从升级EF 4.xEF 6。我必须重新生成连接字符串才能添加表(DatabaseFirst)。我没有注意到app.config和中的连接web.config字符串不同。一旦我connectionstring从接管了app.config,它就开始工作。
DHFW

16

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

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

12

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

脚步:

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

8
首先,EF代码中没有.edmx。
Tuukka Haapaniemi '16

我给了+1,因为他(或其他遇到此问题的人)可能想重新考虑先做代码,然后再这样做:)
vapcguy,

9

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


这对于许多人来说可能是显而易见的,但这是我的问题(关于将db-first与代码优先混合在一起)。现在我可以停止转动车轮了,非常感谢!
Bonez024

3

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


3

我的问题已通过更新连接字符串的元数据部分得到解决。显然,它指向错误的.c​​sdl / .ssdl / .msl参考。


这也发生在我身上。我已经从其他地方复制了EF连接字符串,并且没有更新元数据中的模型名称。
devC

2

还要检查连接字符串的另一件事-型号名称。我使用的是两个实体模型,首先是数据库。在配置中,我复制了一个实体连接,将其重命名,然后更改了连接字符串部分。我没有更改的是模型名称,因此,当实体模型正确生成时,当上下文启动时,EF正在为实体寻找错误的模型。

看起来很明显,但我有四个小时没有回来。


2

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


1

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


1

消息很清楚,但是我一开始没有得到...

我有两个实体框架DB环境工作sysContext,并shardContext在同一个方法。

我修改\更新的实体来自一个上下文,但是我尝试将其保存到另一个上下文中,如下所示:

invite.uid = user.uid;

sysContext.Entry(invite).State = EntityState.Modified;

sysContext.SaveChanges(); // Got the exception here

但是正确的版本应该是这样的:

invite.uid = user.uid;

shardContext.Entry(invite).State = EntityState.Modified;

shardContext.SaveChanges();

将实体传递到正确的上下文后,该错误消失了。


0

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

modelBuilder.Ignore<MyType>();


0

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



0

Visual Studio 2019似乎为我造成了这种情况。我通过在2017年再次生成edmx模型来修复它。


0

我在Entity Framewrok中遇到了同样的问题,并通过以下步骤解决了该问题:

1打开您的Model.edmx 2更改表格位置(在CS文件中进行更改)3保存

希望对你有帮助



0

我在尝试更新值范围时遇到了与EntityFrameworkCore相同的问题。

这种方法行不通

  _dbSet.AttachRange(entity);
  _context.Entry(entity).State = EntityState.Modified;
   await _context.SaveChangesAsync().ConfigureAwait(false);

添加UpdateRange方法并删除附件和条目后,一切正常

  _dbSet.UpdateRange(entity);
  await _context.SaveChangesAsync().ConfigureAwait(false);


0

可能很愚蠢,但是如果您仅在某些表上遇到此错误,请不要忘记清理项目并重建(可以节省很多时间)


0

我有这个

using (var context = new ATImporterContext(DBConnection))
{
    if (GetID(entity).Equals(0))
    {
        context.Set<T>().Add(entity);
    }
    else
    {
        int val = GetID(entity);
        var entry = GetEntryAsync(context, GetID(entity)).ConfigureAwait(false);
        context.Entry(entry).CurrentValues.SetValues(entity);

    }
    
    await context.SaveChangesAsync().ConfigureAwait(false);
}

这是在异步方法中,但是我忘了在GetEntryAsync之前等待,所以我遇到了同样的错误...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.