Creating a Breeze Entity including navigationproperties using manager.createEntity throws exception - entity-framework

Scenario:
I use breeze for querying in our SPA and raw http methods for POST PUT DELETE methods.
A POST method on a resource returns the created resource including it's created childobjects.
I want to attach this created resource to the beeze entity manager.
I've tried adding the entity using
manager.createEntity('Driver', data, breeze.EntityState.Unchanged);
where the data object contains the driver resource and an array of related child entities.
But get an exception: "Collection navigation properties may NOT be set."
Do I have to create the local entity by hand and attach the child entities or does breeze support this scenario?

The reason for this exception is that the 'createEntity' method creates the entity and then assigns your 'data' to it, but for any collection navigation properties the collection already exists and Breeze won't allow you to replace it. This was a deliberate choice for existing entities where other parts of the application might hold a reference to the collection, but is overkill in this case where you are the 'first' to access the collection. For now, the workaround is to update any navigation collections instead of replacing them.
So the simplest way to do this is to call the createEntity method without any collection data properties, and then push data into your collections
var driver = manager.createEntity('Driver', dataWithoutCollections, EntityState.Unchanged)
// then update collection properties by pushing into them.
trafficFines.forEach(function(trafficFine) {
driver.trafficFines.push(trafficFine); // or use push.apply
};
Note that adding to an entity's collection properties will not cause an EntityState change so this should be sufficient.
Based on this issue, I will add a feature request to suppress this exception in the case where you are calling the 'createEntity' method, since there is no danger that some other part of the application has already had access to the new entity.

Related

Insert List of Objects using Entity Framework

Hi i am trying to attach multiple objects in ObjectContextManager and try to set their state in "Added" Mode. These objects have some navigational properties with them and when i try to attach any object after attaching the first object. It throws me the error
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
The reason seems to be very obvious but what will be its solution.
Kindly guide
By calling Attach or AddObject on the entity you are actually attaching or adding whole object graph (EF traverse navigation properties and executes the operation on every related property). When you try to add or attach entity which was already attached or added as part of object graph you will get this exception. The solution is to understand your data model and call AddObject or Attach only for disjointed object graphs.
You should initialize the Id of new entities you add/attach with a random Id (like Guid.NewGuid().GetHashCode() if you use Int32 as Id-type)
Otherwise have all entities the default Id of 0, and so will the ObjectStateManager throw an exception when you attach the entities.

How can I create a detached clone of an EF codefirst class for testing purposes?

I want to create an integration test which grabs an EF entity from the DB, clones it to a detached object, modifies it and then saves it back and compares it again to the original.
However, I was using AutoMapper to create the clone of the class, but it turns out this is also tracked or an alias to the original object. I need it to be completely detached from EF, and am able to do this outside of my repository class (i.e. not using any EF detach methods).
The reason for doing this is my EF class contains nested collections of other classes and EF doesn't handle persisting the whole object tree. Hence, my Update() method in my repository class handles this and I want my NUnit test to test this code. I want the test is to be able to quickly create a copy of my original class without EF tracking it.
Creating a cloned object containing current, original, or database
values The DbPropertyValues object returned from CurrentValues,
OriginalValues, or GetDatabaseValues can be used to create a clone of
the entity. This clone will contain the property values from the
DbPropertyValues object used to create it. For example:
using (var context = new UnicornsContext())
{
var unicorn = context.Unicorns.Find(1);
var clonedUnicorn = context.Entry(unicorn).GetDatabaseValues().ToObject();
}
Note that the object returned is not the entity and is not being
tracked by the context. The returned object also does not have any
relationships set to other objects.
The cloned object can be useful for resolving issues related to
concurrent updates to the database, especially where a UI that
involves data binding to objects of a certain type is being used. (See
Part 9 for more details on dealing with optimistic concurrency.)
*From http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx
Hope it can helps others
All troubles are gone once you're using EF 5+ where they introduced AsNoTracking() method.
The line below returns an unlinked instance, so all the context won't be aware about any changes in that instance:
context.Clients.AsNoTracking().FirstOrDefault(item => item.Id == id);
If Clients has a reference to Address and you want an unlinked instance of it too, just use an Include:
context.Clients
.Include("Address").AsNoTracking()
.FirstOrDefault(item => item.Id == id);
If it is a test you can do anything and you don't have to be binded to any architectural approach like repository. Your repository probably receive context as injection so you can have access to it. Another point is that I don't believe that AutoMapper will create tracked entity.
The one way to make a copy of the class is using serialization which by default saves only public fields (Xml serialization or DataContract serialization). Serialize the object and deserialize it back to a new instance. Serialization will save the whole object graph and deserialized object graph will be detached. Just be aware that that those serializations don't likes cyclic references in object graph (navigation property from A to B and from B to A from cycles). Serialization is also too much aggresive so it can traverse the graph more deeply then you want - this can be especially dangerous in many to many relations.
The best approach is using either ICloneable interface and implement Clone or define support methods which will do different clones with required depth.
Here is another approach for clonning EntityObject based entities. It is tough code, especially part with Reflection.Emit. But this will not help you because code-first is using POCOs.

RIA services presentation model with 1-many or many-many relationships

I'm trying to get a presentation model (discussed here and here) working in RIA. All the examples I can find are simple, flat data entities with no 1-many or many-many relationships, which are what I can't get working - specifically, on updates and inserts into associative relationships.
Queries I can get working fine - I have my presentation classes marked up with Association attributes (and Include attributes, where appropriate), and I have a good understanding about how data is loaded into the client side and maintained there as entities. I also have inserts of new entities covered. However, I'm experiencing the following problems. For the following examples, assume we have simple Album and Artist entities, where an Album has a single artist and an Artist can have zero to many albums. Both have a Name property.
On the client side, if I do myArtist.Albums.Add(anAlbum) or myArtist.Albums.Remove(anAlbum), nothing happens. HasChanges returns false. (Note that myArtist and anAlbum were obtained solely in code by loading the entities and iterating to get references to specific entities: I'm not doing anything in UI or with DomainDataSources yet, just dinking around).
If I update the Name on an Artist and SubmitChanges, when the Update method gets called on the server, the Albums collection is null.
Does anyone have any suggestions, or can you point me to an example that uses more complex objects?
EDIT (keeping the above for posterity): Alright, it appears that the second issue (a reference to an entity or a collection of entities showing as null when Update gets called on the server) exists because the child entites aren't marked as Changed and so they aren't being serialized and sent back. I know you can force that to happen by using [Composition] and I have gotten it to work that way, but this is not a compositional relationship and I want both entities to be "top-level" entities. How can I mark an entity as changed?
The problem was that my [Association] attributes weren't correctly defined. I didn't realize that the association's Name property has to be the same on both sides of the association. When the names are the same and you do a build, the generated code on the client uses a different constructor for the EntityCollection used by the "parent" to refer to the "children" than it does if the associations aren't set up right. The new constructor takes callbacks that do a little bit of extra handling when you call Add and Remove on the collection - specifically, they take the child entity you are adding or removing and modify the property on it that refers to its parent so that everything remains in sync: the collection you removed the object from, the collection you added it to, and the object's reference to its parent.

Update A Collection With Entity Framework

I have a detached set of client objects that I'd like to update (I know they already exist in the db by primary key). Now I want to update them to the database. Knowing I need to query them first, I do so and now have to basically take the properties from the deattached objects and apply them to the attached objects. I finally call save changes. Is there a slick way to apply these properties from the detached collection to the attached one?
NOTE: The detached objects don't have the primary keys in them but I do have enough information to link with via a comparer class.
You don't need to do what you're doing. You can just call the Attach method on your ObjectContext to tell it that you want to work with your detatched objects. Then just call SaveChanges to update the database with your changed objects.

Inheritance problems with Entity Framework (table per type)

For part of the project I'm currently working on, I have a set of four tables for syndicatable actions. One table is the abstract base for the other three, and each table is represented in my EF model like so:
EF Model -- Actions http://chris.charabaruk.com/system/files/images/EF+Model+Actions.png
There are two problems that I'm currently facing with this, however. The first problem is that Actor (a reference to a User) and Subject (a reference to an entity of the class associated with each type of action) are null in my subclasses, despite the associated database columns holding valid keys to rows in their associated tables. While I can get the keys via ActorReference and SubjectReference this of course requires setting up a new EF context and querying it for the referenced objects (as FooReference.Value is also null).
The second problem is that the reciprocal end of the relationship between the concrete action classes and their related entity classes always turn up nothing. For example, Task.RelatedActions, which should give me all TaskAction objects where Subject refers to the particular task object on which RelatedActions is called, is entirely devoid of objects. Again, valid rows exist in the database, Entity Framework just isn't putting them in objects and handing them to me.
Anyone know what it is I'm doing wrong, and what I should do to make it work?
Update: Seems that none of the relationship properties are working in my entity model any more, at all. WTF...
I think the issue you are experiencing here is that by default the EF does not automatically load related entities. If you load an entity, the collection or reference to related entities will be empty unless you do one of the following things:
1) Use eager loading in order to retrieve your main entity and your related entity in a single query. To do this, modify your query by adding a call to the Include method. In your sample above, you might use the following query:
from a in context.Actions.Include("Actor") select a
This would retrieve each of the actions with the related Actor method.
2) Use explicit lazy loading to retrieve the related entity when you need it:
action1.ActorReference.Load()
In the version of the EF which will ship with .Net 4.0, you will also have the following additional option:
3) Turn on implicit lazy loading so that related entities will automatically be retrieved when you reference the navigation property.
Danny