EntityFramework 4.0 POCO代理问题

4

我看到很多人提出了类似的问题,但并非这个确切的问题。我正在尝试使用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的属性更改应该改变它的状态,而不仅仅是它的创建。 - ralf.w.
我不确定你想要做什么。你有很多代码,试图做一些事情。但是不清楚你实际想要做什么? - Alex James
问题是:为什么我使用上下文创建新对象时,它没有附加到上下文中,而且当我手动添加时,它的状态为未更改?...它应该是新的... - Jeff
2个回答

1

看起来你想要添加一个新的代理对象,以便EF能够注意到它的更改。

正如StriplingWarrior所提到的,CreateObject<T>只是创建了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(微软)


仅供参考:http://meta.stackexchange.com/questions/5029/are-taglines-signatures-disallowed/5038#5038 - Greg
谢谢 Greg。我没有意识到我正在违反一条不成文的规定。 - Alex James
@Alex - 谢谢你能够平心静气地接受我的意见。我本应该用更友好的方式来表达我的“反对”。 - Greg
但是将我的新对象添加到上下文中后,它的状态仍为未更改,即使它是新的并且尚未插入到数据库中。 - Jeff
除非我非常错了,是的。 - Alex James
显示剩余3条评论

1

我对代理并不熟悉,但看起来你期望它跟踪一个没有持久状态的对象的更改。

CreateEntity只是创建对象。这与说“new 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 不能跟踪对新代理对象的更改,除非它已经被持久化了??如果你的意思是这个的话,那就可以解释很多问题了... - Jeff
1
无论 EF 是否能够追踪新对象的更改并不重要,重要的是 EF 不需要追踪新对象的更改。为什么呢?因为没有先前的版本,所以你可以直接插入最新版本!只有在需要知道现有属性值需要更改时才需要进行属性级别的更改追踪。 - Alex James
那么,假设我使用CreateObject<T>创建了我的代理,并且后来想确定我的对象是新对象还是通过LINQ查询从数据存储中检索的对象。我该怎么做? - Jeff
当对象被持久化到数据存储中时,Entity Framework会分配其主键值。通常我会检查标识键是否为0。但是可能有某个实用方法可以实际检查对象是来自数据存储还是已创建但尚未持久化。 - StriplingWarrior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接