views:

271

answers:

2

I see a lot of people asking a similar question, but not this exact one. I'm trying to do what I would hope would be relatively simple with POCO proxies.

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);
}

What am I doing wrong? Thanks!

+1  A: 

It looks like you want to add a new proxy object so EF can notice changes to it.

As mentioned by StriplingWarrior CreateObject<T> simply creates a proxied version of T, you have to Add it (for inserts) or Attach it (for updates) for EF to learn about it.

Reading between the lines in your code it looks like you want to do an insert?

If that is indeed the case a Proxy isn't even really required.

Why?

Well you don't need property level change tracking (i.e. to know what properties have changed) all you need to know is that the object is new and should be inserted.

Add calling ctx.MyEntities.Add(...) tells EF that.

Which means for inserts this is enough:

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

Or this

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

will both work. But the former is easier to understand.

Hope this helps

Alex (Microsoft)

Alex James
For reference: http://meta.stackoverflow.com/questions/5029/are-taglines-signatures-disallowed/5038#5038
Greg
Thanks Greg. I didn't realize I was flouting an unwritten rule.
Alex James
Alex: The rule is in the FAQ (towards the bottom).
Gabe
@Alex - Thanks for taking it well. I should have worded my "objection" in a more friendly manner.
Greg
But adding my new object to the context leaves it with a status of Unchanged, even though it is new and has not been inserted into the DB yet.
JeffN825
Sure but if you call SaveChanges it will be inserted. What it means is Unchanged since the last insert.
Alex James
So, even if it says Unchanged, it will still be inserted? If so, that answers my question.
JeffN825
Unless I'm very much mistaken, yes.
Alex James
+1  A: 

I haven't done much with proxies, but it looks like you're expecting it to track changes on an object that has no persistent state yet.

CreateEntity really just creates the object. It's no different than saying "new MyEntity". So you have to add that entity to the context and save the changes before it has any true "state" to track against:

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.
    // ...
}
StriplingWarrior
So you're saying that EF CAN'T track changes against a new proxy object, unless it's been persisted first?? That would explain a lot if that's what you mean...
JeffN825
It doesn't really matter whether EF can track changes to a new object or not, what matters is EF doesn't need to track changes to new objects. Why: There isn't a previous version, so you can just insert the latest version! Property level change tracking is only required when you need to know what *existing properties value* need to change.
Alex James
So, let's say I have my proxy that I created with CreateObject<T> and later on want to determine if my object is in fact a new object or one I retrieved from the data store via a LINQ query. How would I do this?
JeffN825
When the object is persisted to the data store, Entity Framework assigns its primary key value. I generally check to see if the identity key is `0`. But there may be a utility method somewhere to actually check whether the object came from the data store or was created and not yet persisted.
StriplingWarrior