简体   繁体   English

实体框架代码首先为映射到相同类的不同表返回相同数据

[英]Entity Framework Code First returning same data for different tables mapped to same class

I have a class Timer which I want to use with different tables that have the same structure so I am passing in the table name. 我有一个Timer类,希望与结构相同的不同表一起使用,因此我要传递表名。

public class TimerContext : DbContext
{
    public DbSet<Timer> Timers { get; set; }

    private readonly string _tableName;

    public TimerContext(string tableName) : base("name=fooDb")
    {
        _tableName = tableName;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Timer>().ToTable(_tableName);

        base.OnModelCreating(modelBuilder);
    }
}

However when I pass in two different table names they return the same data. 但是,当我传入两个不同的表名时,它们将返回相同的数据。 prevTimers contains the exact same data as currTimers . prevTimers包含完全相同的数据currTimers How do I get the unique data from each table? 如何从每个表中获取唯一数据? Why do I get the same data for two different tables? 为什么要为两个不同的表获得相同的数据?

var currTimers = new TimerContext(currentTimerTableName).Timers.ToList();
var prevTimers = new TimerContext(previousTimerTableName).Timers.ToList();

EF will call the OnModelCreating method to create an in-memory copy of the model as soon as it is needed. EF将在需要时调用OnModelCreating方法来创建模型的内存中副本。 Once it has done this, this copy will be used. 完成此操作后,将使用此副本。 In your case, the code to generate prevTimers uses this in-memory model which is mapped to the current timers table . 在您的情况下,生成prevTimers的代码使用此内存中模型,该模型映射到当前timers表 If you place a breakpoint on the OnModelCreating method, you should see that it is only called one time. 如果在OnModelCreating方法上放置一个断点,则应该看到它仅被调用一次。

All that said, it is possible to dig deep and interrogate the in-memory model (you have to use the old school context type, ObjectContext vs. DbContext). 综上所述,可以深入研究内存模型(您必须使用旧的上下文类型ObjectContext vs. DbContext)。 Using some code from Rowan Miller here , you can find which table is mapped to each entity set. 使用此处的 Rowan Miller的一些代码,您可以找到将哪个表映射到每个实体集。 Using this code, each item in the tables variable has a read / write Table property that contains the database table name. 使用此代码,表变量中的每个项目都有一个包含数据库表名称的读/写表属性。 I haven't tried setting this but it certainly seems plausible. 我没有尝试设置此设置,但似乎确实可行。 Of course, you would need to alter the model somewhere else outside of the OnModelCreating method, say in the constructor, so that the code will fire each time an instance of the context is created. 当然,您需要在OnModelCreating方法之外的其他地方(例如在构造函数中)更改模型,以便每次创建上下文实例时都将触发代码。

* UPDATE * *更新*

Because I am always interested in learning new things, I couldn't leave this alone and threw together a test application. 因为我一直对学习新事物很感兴趣,所以我不能不去管它,而把一个测试应用程序放在一起。 Unfortunately, it looks like you cannot set the property (despite it being a read / write property) as it throws an InvalidOperationException stating that the item is read-only. 不幸的是,您似乎无法设置该属性(尽管它是一个读/写属性),因为它引发了一个InvalidOperationException异常,指出该项目是只读的。 Perhaps there is another way but I have not found it...yet. 也许还有另一种方法,但是我还没有找到……。

* UPDATE * *更新*

The solution is actually much simpler that what I had first mentioned. 实际上,该解决方案比我最初提到的要简单得多。 A couple of the constructors of the DbContext class accepts an instance of the DbCompiledModel class as one of its parameters. DbContext类的几个构造函数接受DbCompiledModel类的实例作为其参数之一。 Using the DbModelBuilder class, you can build the same code that you would normally put in the OnModelCreating method. 使用DbModelBuilder类,您可以构建与通常放在OnModelCreating方法中相同的代码。 You can call the Build method of this class to create an instance of the DbModel class. 您可以调用此类的Build方法来创建DbModel类的实例。 You can call the Compile method of this class to create an instance of the DbCompiledModel class. 您可以调用此类的Compile方法来创建DbCompiledModel类的实例。 The only real trick is that the Build method requires some additional information (I used an instance of the DbProviderInfo class but I think you could also use an actual connection but that would probably incur a hit to the database). 唯一真正的窍门是Build方法需要一些其他信息(我使用了DbProviderInfo类的实例,但我认为您也可以使用实际的连接,但这很可能会损坏数据库)。 I have tested this and this one does indeed work as desired. 我已经对此进行了测试,并且确实可以按预期工作。

Something like... 就像是...

DbModelBuilder builder = null;

builder = new DbModelBuilder();
builder.Entity<TestEntity>().ToTable(tableName);

DbModel model1 = null;

model1 = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2012"));

builder.Entity<TestEntity>().ToTable(anotherTableName);

DbModel model2 = null;

model2 = builder.Build(new DbProviderInfo("System.Data.SqlClient", "2012"));

DbCompiledModel compiledModel1 = null;
DbCompiledModel compiledModel2 = null;

compiledMdoel1 = model1.Compile();
compiledMdoel2 = model2.Compile();

TestContext context1 = null;
TestContext context2 = null;

context1 = new TestContext(compiledModel1);
context2 = new TestContext(compiledModel2);

Of course, the constructor of the TestContext class would have to pass the compiled model instance to the base constructor. 当然,TestContext类的构造函数必须将编译后的模型实例传递给基本构造函数。

cannot add comment, but I just want to add one thing that happened to me 无法添加评论,但我只想添加发生在我身上的一件事

my code was like this: 我的代码是这样的:

DbModelBuilder builder = new DbModelBuilder();
this.OnModelCreating(builder);
var model = builder.Build(this.Database.Connection);

I was thought that when i pass the current DbConnection object to this method, it will somehow "inherit" of all connection settings, but seems I was wrong. 我以为,当我将当前的DbConnection对象传递给此方法时,它将以某种方式“继承”所有连接设置,但似乎我错了。 After debugging a while, i just realize it generate some weird connection string for me, which always results in cannot find database issue. 经过一段时间的调试,我才意识到它会为我生成一些奇怪的连接字符串,这总是导致找不到数据库问题。 So my solution is, when instantiate the "TestContext" (as in Jason Richmeier's answer ), pass nameOrConnectionString as first parameter and the compiled model as second, and it solved my issue. 所以我的解决方案是,当实例化“ TestContext”(如Jason Richmeier的答案 )时,将nameOrConnectionString作为第一个参数,将编译后的模型作为第二个参数,就解决了我的问题。

I wonder, since EF keep a in-memory copy of certain model, is manually create another one will just create a new copy in memory? 我想知道,由于EF保留了某个模型的内存副本,是否手动创建另一个会在内存中创建一个新副本? And if my code need to do this a lot of times, it is going to keep creating new models in memory and finally ends with a memory overflow? 如果我的代码需要多次执行此操作,它将继续在内存中创建新模型,最后以内存溢出结束吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 首先在不同架构中映射具有相同表的实体 Entity Framework 6 代码 - Map entity with same table in different schemas Entity Framework 6 code first 实体框架代码类的第一个属性和相同类的列表 - Entity Framework Code First One Property of Class and List of The Same Class 实体框架代码优先-派生类与基类不在同一程序集中 - Entity Framework code first - Derived class not in the same assembly as the base class 如何将相同 class 的两个列表拆分为实体框架中的不同表? - How to split two lists of the same class to different tables in Entity Framework? 实体框架代码优先 - 两个具有相同名称但位于不同名称空间的实体 - Entity Framework Code First - two entities with same name but in different namespaces 实体框架代码与同一类的第一个双重关系 - Entity Framework Code First double relation to same class 使用实体框架代码优先映射相同 class 的子项 - Mapping child items of same class with Entity Framework Code First 实体框架实体不同的键映射到同一行 - Entity Framework entities different keys are mapped to same row 实体框架代码优先 - 引用相同的表 - Entity Framework Code First - Reference same table FK到同一个表代码第一个实体框架 - FK to the Same Table Code First Entity Framework
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM