![](/img/trans.png)
[英]Map entity with same table in different schemas Entity Framework 6 code first
[英]Entity Framework Code First returning same data for different tables mapped to same class
我有一个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);
}
}
但是,当我传入两个不同的表名时,它们将返回相同的数据。 prevTimers
包含完全相同的数据currTimers
。 如何从每个表中获取唯一数据? 为什么要为两个不同的表获得相同的数据?
var currTimers = new TimerContext(currentTimerTableName).Timers.ToList();
var prevTimers = new TimerContext(previousTimerTableName).Timers.ToList();
EF将在需要时调用OnModelCreating方法来创建模型的内存中副本。 完成此操作后,将使用此副本。 在您的情况下,生成prevTimers的代码使用此内存中模型,该模型映射到当前timers表 。 如果在OnModelCreating方法上放置一个断点,则应该看到它仅被调用一次。
综上所述,可以深入研究内存模型(您必须使用旧的上下文类型ObjectContext vs. DbContext)。 使用此处的 Rowan Miller的一些代码,您可以找到将哪个表映射到每个实体集。 使用此代码,表变量中的每个项目都有一个包含数据库表名称的读/写表属性。 我没有尝试设置此设置,但似乎确实可行。 当然,您需要在OnModelCreating方法之外的其他地方(例如在构造函数中)更改模型,以便每次创建上下文实例时都将触发代码。
*更新*
因为我一直对学习新事物很感兴趣,所以我不能不去管它,而把一个测试应用程序放在一起。 不幸的是,您似乎无法设置该属性(尽管它是一个读/写属性),因为它引发了一个InvalidOperationException异常,指出该项目是只读的。 也许还有另一种方法,但是我还没有找到……。
*更新*
实际上,该解决方案比我最初提到的要简单得多。 DbContext类的几个构造函数接受DbCompiledModel类的实例作为其参数之一。 使用DbModelBuilder类,您可以构建与通常放在OnModelCreating方法中相同的代码。 您可以调用此类的Build方法来创建DbModel类的实例。 您可以调用此类的Compile方法来创建DbCompiledModel类的实例。 唯一真正的窍门是Build方法需要一些其他信息(我使用了DbProviderInfo类的实例,但我认为您也可以使用实际的连接,但这很可能会损坏数据库)。 我已经对此进行了测试,并且确实可以按预期工作。
就像是...
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);
当然,TestContext类的构造函数必须将编译后的模型实例传递给基本构造函数。
无法添加评论,但我只想添加发生在我身上的一件事
我的代码是这样的:
DbModelBuilder builder = new DbModelBuilder();
this.OnModelCreating(builder);
var model = builder.Build(this.Database.Connection);
我以为,当我将当前的DbConnection对象传递给此方法时,它将以某种方式“继承”所有连接设置,但似乎我错了。 经过一段时间的调试,我才意识到它会为我生成一些奇怪的连接字符串,这总是导致找不到数据库问题。 所以我的解决方案是,当实例化“ TestContext”(如Jason Richmeier的答案 )时,将nameOrConnectionString作为第一个参数,将编译后的模型作为第二个参数,就解决了我的问题。
我想知道,由于EF保留了某个模型的内存副本,是否手动创建另一个会在内存中创建一个新副本? 如果我的代码需要多次执行此操作,它将继续在内存中创建新模型,最后以内存溢出结束吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.