【问题标题】:EntityFramework 4.0 POCO Proxy ProblemEntityFramework 4.0 POCO 代理问题
【发布时间】:2011-03-30 05:04:50
【问题描述】:

我看到很多人都在问类似的问题,但不是这个问题。我正在尝试做我希望使用 POCO 代理相对简单的事情。

using (var context = new MyObjectContext())
{
    context.ContextOptions.ProxyCreationEnabled = true;

    // this does indeed create an instance of a proxy for me...
    // something like Product_SomeBunchOfNumbersForProxy
    var newEntity = context.CreateObject<MyEntity>();

    // throws exception because newEntity is not in ObjectStateManager...why??
    context.ObjectStateManager.GetObjectStateEntry(newEntity);

    // ok, well I guess let's add it to the context manually...
    context.AddObject("Model.Products", newEntity);

    // doesn't throw an exception...I guess that's good
    var state = context.ObjectStateManager.GetObjectStateEntry(newEntity); 

    // prints System.Data.EntityState.Unchanged...oh...well that's not good
    Console.WriteLine(state.State);

    // let's try this...
    context.DetectChanges();

    // doesn't throw an exception...I guess that's good
    state = context.ObjectStateManager.GetObjectStateEntry(newEntity);

    // prints System.Data.EntityState.Unchanged...still no good...
    Console.WriteLine(state.State);

    // dunno, worth a shot...
    context.Refresh(RefreshMode.ClientWins);

    // throws exception because newEntity is not in ObjectStateManager...
    // that didn't help...
    state = context.ObjectStateManager.GetObjectStateEntry(newEntity);
}

我做错了什么?谢谢!

【问题讨论】:

  • 我认为 newEntity 的一些属性更改应该改变它的状态,而不仅仅是它的创建。
  • 我不确定你到底想做什么。你有很多代码,试图做一些事情。但目前还不清楚你真正想要做什么?
  • 问题是:为什么我的新对象在我使用上下文创建它时没有附加到上下文 - 为什么当我手动添加它时它的状态没有改变?...它应该是新的...

标签: c# .net entity-framework entity-framework-4 poco


【解决方案1】:

您似乎想添加一个新的代理对象,以便 EF 注意到它的更改。

正如 StriplingWarrior CreateObject&lt;T&gt; 所提到的,它只是创建了一个 T 的代理版本,您必须添加它(用于插入)或附加它(用于更新),以便 EF 了解它。

在您的代码行之间阅读,您似乎想要进行插入?

如果确实如此,甚至不需要代理。

为什么?

好吧,您不需要属性级别的更改跟踪(即知道哪些属性已更改),您只需要知道该对象是新的并且应该被插入。

添加调用 ctx.MyEntities.Add(...) 告诉 EF。

这对于插入来说就足够了:

var entity = new MyEntity();
... // set some props
ctx.MyEntities.Add(entity);
... // sets some more props
ctx.SaveChanges(); 

或者这个

var entity = ctx.CreateObject<MyEntity>();
... // set some props
ctx.MyEntities.Add(entity);
... // sets some more props
ctx.SaveChanges(); 

两者都可以。但前者更容易理解。

希望对你有帮助

亚历克斯(微软)

【讨论】:

  • 谢谢格雷格。我没有意识到我在藐视一条不成文的规则。
  • Alex:规则在常见问题解答中(朝向底部)。
  • @Alex - 感谢您接受它。我应该以更友好的方式表达我的“反对”。
  • 但是将我的新对象添加到上下文中会使其状态保持不变,即使它是新对象并且尚未插入数据库。
【解决方案2】:

我对代理做的不多,但您似乎希望它能够跟踪尚未具有持久状态的对象的更改。

CreateEntity 实际上只是创建对象。这与说“新的 MyEntity”没有什么不同。因此,您必须将该实体添加到上下文中并保存更改,然后才能跟踪它的任何真实“状态”:

using (var context = new MyObjectContext())
{
    context.ContextOptions.ProxyCreationEnabled = true;
    var newEntity = context.CreateObject<MyEntity>();
    context.Add(newEntity);
    context.SaveChanges();
    // now GetObjectStateEntry(newEntity) should work just fine.
    // ...
}

【讨论】:

  • 所以你是说 EF 不能跟踪新代理对象的变化,除非它首先被持久化?如果这就是你的意思,那将解释很多......
  • EF 是否可以跟踪对新对象的更改并不重要,重要的是 EF 不需要跟踪对新对象的更改。原因:没有以前的版本,所以你可以插入最新的版本!仅当您需要了解现有属性值需要更改的内容时,才需要进行属性级别更改跟踪。
  • 所以,假设我有我用 CreateObject 创建的代理,然后想确定我的对象实际上是一个新对象还是我通过 LINQ 从数据存储中检索到的对象询问。我该怎么做?
  • 当对象被持久化到数据存储时,Entity Framework 分配它的主键值。我一般会检查身份密钥是否为0。但是在某个地方可能有一个实用方法来实际检查对象是来自数据存储还是已创建但尚未持久化。
猜你喜欢
  • 1970-01-01
  • 2012-02-28
  • 2011-12-31
  • 2011-05-20
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2014-08-30
相关资源
最近更新 更多