Entity Framework Save with Children - entity-framework

We have recently decided to use EF6 code first in one of our projects so I am undergoing a paradigm change. I really enjoy EF but some things are so different they seem wrong.
I just want to run a scenario by the community to see if I am thinking correctly.
We have an entity that has child entities of the same type.
If I was saving a child normally I would just save a new entity with the parent id set to the id of the parent. In the entity world they are connected through a navigation property of the same type as follows:
public class SomeType
{
public id;
....
public virtual IList<SomeType> Children
}
Obviously the standard approach doesn't work here since I am not manipulating DB foreign keys manually.
It seems the "Entity Way" would be to first use DBCcontext and linq to select the parent, then add the new entity to the Children list and save the whole thing.
Which is fine and logical - but it just seems a little inefficient to do a select every time i am doing a save.
Am I really missing something here do I just need to get used to a different way of thinking here?
Thank you!

If I'm getting your problem right, then you can and should save the child as a simple Sometype with a parentId, just as you would without using the entity framework. The automagic of the EF shouldn't cause a problem for you here, and you would not be breaking any best practices.
Essentially: If the parent entity is already loaded into context, it's usually best to add the new entity to the collection of navigation properties (Children in your case, but any foreign key). If the parent is not loaded and you know it's id, populate the foreign key field and save it just as you always did.

Related

Entity Framework, Link tables and mapping multiple tables to a single entity

I have an Entity called "Product", this entity, through table mapping, merges 6 tables that have a 1 to 1..0 relationship with "Products". This all works wonderfully. There is another property I want to add to "Products", which is sBBR_rate, this value is not in a table that has a direct 1 to 1..0 relationship, it is related through a link table as below:
When I import the two tables into the EDM, I can't see a way in the "Mapping Details" of
"Product" to reference the sBBR_rate. I can reference RatesLink and link that to the "Products" primary key, however, I cannot reference the BBR table.
The methods I can think of to work "around" this is are as follows:
Create a view, reference the view in the EDM.
Create an SP and use a function import to retrieve the BBR when it is required.
Create a "Rates" entity in the EDM that can then draw down the sBBR_rate into it. Navigate to the Products BBR through Product.Rates.sBBR_rate.
Is there a better way I can do this that doesn't feel so much like a fudge? Perhaps by directly editing the XML of the Mapping or Conceptual layers of the EDM?
Thanks for your input.
Because the multiplicities on the Product -> RatesLink and RatesLink -> BBR relationships are 0 to 1, you should be able to access the sBBR_rate from a Product instance like this:
myProductInstance.RatesLink.BBR.sBBR_rate
I can see on the EDM screenshot that RatesLink has a Product and BBR property, which would indicate this should be available - is it?
On a side note, if it makes sense for the sBBR_rate property to commonly be accessed directly from Product, you might want to follow the law of demeter and create a property on Product which returns it directly.
The model we are using is to extend entities by using partial classes which we've found useful so we can get additional properties in the autogenerated classes (we are using a POCO T4 template to autogen but I believe this would work just as well with the default entity object generation).
So we would have
//.. this one is from the T4 template
public partial class Product
{
//.. all the autogenerated methods
}
and in a separate file that isn't autogened
//.. now in a separate file created by me
public partial class Product
{
//.. my custom properties and methods to make the entities more usable
public string BBRRate
{
get {return this.RatesLink.BBR.sBBR_rate; }
}
}
This means that I can just do
myProduct.BBRRte
I know there are other ways to do this by amending the edmx file but this one we found easy to implement. You just need to watch performance because you are potentially loading extra data. Also we did this with LazyLoading turned on but with more work you wouldn't have to
We also experimented with hooking into the ObjectMaterialized event in the ObjectContext class to preload some of these properties. Using a custom interface i.e. IMaterialisable we could check if the object was of that type then call a method (Materialise) to prepopulate some of the properties. This seems like a good idea but we didn't widely use it - it was easy to load up too much stuff. If you do the load on the properties in the partial classes then it becomes more efficient. Just my experience.
Anyway - as always an interesting question and good luck again with your dev.
EDIT
There is a rule that everything in the store layer must be represented some way in your conceptual layer. Therefore removing the tables from the conceptual layer but bring through some of the properties I don't think will work in it's gross form. Therefore I can think of two further options
Create a View on the database and bring that in as you have already mentioned. TBH this is what I would do.
Use the DefiningQuery element directly in your xml (the store layer) and map the query through to a custom entity of your exact design. Julie Lerman describes this as the ultimate escape hatch for Entity Framework.
Remember though - if you manual amend the XML in point 2 then you lose the ability to automatically update the module through the IDE
I ended up creating a view and then linking this view in the EDM, this worked a treat.

Deleting child objects in Entity Framework when using POCO

I'm using POCO with EF4 and have problem deleting a child object from the parent. Consider the following scenario:
public class Order
{
public List<OrderItem> Items { get; private set; }
}
I need to delete an OrderItem from an Order object like:
myOrder.Items.Remove(0);
I expect EF to keep track the changes and delete the associated OrderItem when I call ObjectContext.SaveChanges().
However, I have realized this is not possible without calling Context.DeleteObject(). I believe this is not a true POCO way as my domain model shouldn't be aware of my persistence infrastructure.
Does anyone have a work around this issue?
Cheers,
Mosh
However, I have realized this is not
possible without calling
Context.DeleteObject(). I believe this
is not a true POCO way as my domain
model shouldn't be aware of my
persistence infrastructure.
I would not follow your interpretation. If you have in-memory collections of orders and order items (ignoring the persistence infrastructure), it's a difference if you only remove an item from the order's item collection or if you also delete the item from the in-memory repository. It might be possible that you want to remove the item only from one order, keep it existing and assign it to another order. (It wouldn't probably make much sense in case of orders and order items, but that's business logic and your POCOs and their relationships cannot know that you want to delete the item from the repository everytime you remove it from an order.)
So, you have to tell explicitely that the item should be deleted from the repository - for an in-memory repository and for a persistence related repository as well. You have to call DeleteObject for the item, there is no workaround to avoid this.
What referential integrity do you have setup in the DB? You have only asked for the orderitem to be removed from the item - not for it to be deleted, and that is what is happening.

Entity Framework - Foreign key constraints not added for inherited entity

It appears to me that a strange phenomenon is occurring with inherited entities (TPT) in EF4.
I have three entities.
1. Asset
2. Property
3. Activity
Property is a derived-type of Asset.
Property has many activities (many-to-many)
When modeling this in my EDMX, everything seems fine until I try to insert a new Property into the database. If the property does not contain any Activity, it works, but all hell breaks loose when I add some new activities to the new Property.
As it turns out after 2 days of crawling the web and fiddling around, I noticed that in the EF store (SSDL) some of the constraints between entities were not picked up during the update process.
Property_Activity table which links properties and activities show only
one constraint
FK_Property_Activity_Activity but
FK_Property_Activity_Property was
missing.
I knew this is an Entity Framework anomoly because when I switched the relationship in the database to:
Asset <--> Asset_Activity <--> Activity
After an update, all foreign key constraints are picked up and the save is successful, with or without activities in the new property.
Is this intended or a bug in EF?
How do I get around this problem?
Should I abandon inheritance altogether?
Not a but but a poor visual designer.
Its generally best to simply manage the Entity XML by hand.
No inheritance works well for many situations.
Basically I use the update from database in the visual designer but knowing that the designer has its quirks. I have simply used the update from database to stub out the basics of what I want. Then I go into the Entity XML my self and clean it up the way I want. Just of note Complex types are a pain with the designer. If you plan to use complex types get ready to learn your Entity XML well.

Finding Entity Framework contexts

Through various questions I have asked here and other forums, I have come to the conclusion that I have no idea what I'm doing when it comes to the generated entity context objects in Entity Framework.
As background, I have a ton of experience using LLBLGen Pro, and Entity Framework is about three weeks old to me.
Lets say I have a context called "myContext". There is a table/entity called Employee in my model, so I now have a myContext.Employees. I assume this to mean that this property represents the set of Employee entities in my context. However, I assume wrong, as I can add a new entity to the context with:
myContext.Employees.AddObject(new Employee());
and this new Employee entity appears nowhere in myContext.Employees. From what I gather, the only way to find this newly added entity is to track it down hiding in the myContext.ObjectStateManager. This sounds to me like the myContext.Employees set is in fact not the set of Employee entities in the context, but rather some kind of representation of the Employee entities that exist in the database.
To add further to this confusion, Lets say I am looking at a single Employee entity. There is a Project entity that has a M:1 relationship with Employee (an employee can have multiple projects). If I want to add a new project to a particular employee, I just do:
myEmployee.Projects.Add(new Project());
Great, this actually adds the Project to the collection as I would expect. But this flies right in the face of how the ObjectSet properties off of the context work. If I add a new Project to the context with:
myContext.Projects.AddObject(new Project());
this does not alter the Projects set.
I would appreciate it very much if someone were to explain this to me. Also, I really want a collection of all the Employees (or Projects) in the context, and I want it available as a property of the context. Is this possible with EF?
An ObjectSet is a query. Like everything in LINQ, it's lazy. It does nothing until you either enumerate it or call a method like .Count(), at which point a database query is run, and any returned entities are merged with those already in the context.
So you can do something like:
var activeEmployees = Context.Employees.Where(e => e.IsActive)
...without running a query.
You can further compose this:
var orderedEmployees = activeEmployees.OrderBy(e => e.Name);
...again, without running a query.
But if you look into the set:
var first = orderedEmployees.First();
...then a DB query is run. This is common to all LINQ.
If you want to enumerate entities already in the context, you need to look towards the ObjectStateManager, instead. So for Employees, you can do:
var states = EntityState.Added || EntityState.Deleted || // whatever you need
var emps = Context.ObjectStateManager.GetObjectStateEntries(states)
.Select(e => e.Entity)
.OfType<Employee>();
Note that although this works, it is not a way that I would recommend working. Typically, you do not want your ObjectContexts to be long-lived. For this, and other reasons, they are not really suitable to be a general-purpose container of objects. Use the usual List types for that. It is more accurate to think of an ObjectContext as a unit of work. Typically, in a unit of work you already know which instances you are working with.

*Not* using navigation properties with Entity Framework?

Does anyone know if it's possible to not use the navigation properties feature of the entity framework for tables linked with a foreign key?
for example, if my client table has an AddressId, I want that AddressId in my model, I don't want it to have a .Address property. But I have thus far been unable to figure out how to do this.
Sure, you can do this. It's just that the designer won't help you very much. Delete the navigation property, and add a scalar property for AddressId. It will work, but you'll have to be careful about hitting Update Model in the designer, as it may try to "fix" things for you. It's worth getting used to editing EDMX; it's not that bad.
In the designer, you can set the navigation properties as having Private getters/setters. While they will still be there, because Entity Framework (by default) does lazy loading, it won't actually retrieve any data from the database at runtime. And they won't respawn the next time you update the model from the database.