Entity Framework 4: Can you duplicate an entity and alter it based on filter condition - entity-framework

Is there a way within the entity framework designer to duplicate an entity and then apply a filter condition to both to make them unique. Id like to retain all navigation properties and what not.
For example, say in the database I had a table of orders. I could have two entities, one called IncompleteOrders and One called Complete based on the same table, with the complete having a filter specified on the database field 'complete'.
Thanks in advance

Yes, this is called Table per Hierachy
You have one physical table, which has a special, single, scalar column which is used as a discriminator.
Like this:
OrderId OrderName IsComplete
1 Foo 1
2 Bar 1
3 FooBar 0
Where IsComplete is the discriminator (BIT column, for example), so when you setup your entities on your EDMX, you create three entities:
1. Orders
2. CompleteOrders (derives from Orders)
3. InCompleteOrders (derives from Orders)
On the table mapping for Orders, you say "Maps to CompleteOrders, when IsComplete = 1", and "Maps to InCompleteOrders, when OrderType = 0".
Good writeup on TPH/Discriminator pattern here.

Related

Allowing duplicate records in Core Data Many-to-many relationship

I have an Item and Person relationship which is a many to many relationship.
I want a person to be able to own 2 different instances of an item (which are represented by the same record in the DB). I want my link table to be able to look something like:
Person ID | Item ID
1 | 3
2 | 4
1 | 3
Unfortunately when a person's items are represented by NSSet. So when I try to set an additional dupe object in the set, I'm guessing NSSet automatically removes it.
Any help?
Create a real entity between the Person and Item entity. Then you can create as many of those "join" entities as you want. Or you can stick another attribute in there such as "quantity" instead of having multiple join entities.

EF how to update many to many join table

I am having trouble getting Entity Framework 4 to handle a bulk update in a m2m join. I have several many to many joins in my model, for example something like
Practice
PracticeID PK
Name...
PracticeSpecialties (join table)
PracticeID PK
SpecialtyID PK
Specialties
SpecialtyID pk
Name...
Pretty basic and EF 4 handles it well. My problem is I need to be able to "merge" 2 or more Specialties into 1, for example "Pediatrics" and "Children" and "Adolescents" should all be the same item. So if Pediatrics has a SpecialtyID of 1 and Children = 3 and Adolescents = 9 the query should perform an update on all rows in PracticeSpecialties where SpecialtyID IN (3, 9) and change the value to 1.
I can write a stored proc that would update do this all rows in the join table containing one of the undesired SpecialtyIDs then delete all the now orphaned Specialties, but if possible I am trying to stick with the EF pattern.
Any guidance is appreciated.
In entity framework you must do it in object way = you can simply modify junction table. You must work with objects in navigation properties. Your scenario will look like:
var children = context.Specialities.Include("Practices")
.Single(s => s.Name == "Children");
var pediatrics = context.Specialities.Include("Practices")
.Single(s => s.Name == "Pediatrics");
foreach (var practice in children.Practices)
{
pediatrics.Practices.Add(practice);
}
children.Practices.Clear();
context.Specialities.DeleteObject(children);
context.SaveChanges();
You should also override Equals and GetHashCode in Practice entity and use HashSet for Speciality.Practices (in case of POCOs). It will handle duplicities for you.
Result of this will be multiple deletes and inserts to junction table. This is EF way to do that.
Do not use many-to-many relationships. The join table ends up holding more data eventually anyway. Use a one-to-many and a many-to-one combination instead. If you want, you can make a property that holds the created/modified dates in the middle entity for now.
Hope this helps.

Is this possible to model a "foreign key" into multiple tables with Entity Framework?

I have a MS SQL 2008 database, and I can't change its schema. I have to work with what it is.
It has three tables that relevant to the question.
Product table. The columns are:
Id (identity, PK)
Group (NOT NULL)
SubGroup (NOT NULL)
Code (Unique, NOT NULL)
Description
Contract table. The columns are:
Id (identity, PK)
Code (NOT NULL)
Descritpion
Discount table. The columns are:
Id (identity, PK)
Type (restricted to one of the four values:
'product',
'group',
'subgroup' or
'contract') (NOT NULL)
Object (depending on the value of Type refers one of the four:
Product.Code
Product.Group
Product.SubGroup
Contract.Code) (NOT NULL)
Value (NOT NULL)
The idea is that the discount can be applied to either of the four. I'd like to reiterated, that this is the database design that I can't change.
With Entity Framework I can query the tables all right with joins but I can't use navigation properties out of the box, because navigation properties are generated based on foreign key relationships from database, and you can't define "conditional" relationship in MS SQL, where the field object relates to one table when field type contains this value and relates to another table when the value is different.
My question is this: Is this possible to define classes and mappings with Entity Framework, so that I can use navigation properties in this scenario? For example, I do Discount.Object and I receive either Contract object or Product object in response, and if this is a Product object it's retrieved on the right property.
Is this, or something similar possible, or joins is the best I can do?
You said that "this is the database design that I can't change", but without changing existing tables, can you at least add views?
If you can, you can create a view for the Discount table that has four different nullable columns for each relationship. That would map nicely in EF as four navigation properties.
After you do that, if you still want a combined column, you could add your own property to the Discount entity that will return an object by checking which of the four navigation properties is not null, and returning the linked entity.
You cannot create a relational database like this. You need separate columns for the keys to each potential parent row.

Entity Framework many-to-many question

Please help an EF n00b design his database.
I have several companies that produce several products, so there's a many-to-many relationship between companies and products. I have an intermediate table, Company_Product, that relates them.
Each company/product combination has a unique SKU. For example Acme widgets have SKU 123, but Omega widgets have SKU 456. I added the SKU as a field in the Company_Product intermediate table.
EF generated a model with a 1:* relationship between the company and Company_Product tables, and a 1:* relationship between the product and Company_Product tables. I really want a : relationship between company and product. But, most importantly, there's no way to access the SKU directly from the model.
Do I need to put the SKU in its own table and write a join, or is there a better way?
I just tested this in a new VS2010 project (EFv4) to be sure, and here's what I found:
When your associative table in the middle (Company_Product) has ONLY the 2 foreign keys to the other tables (CompanyID and ProductID), then adding all 3 tables to the designer ends up modeling the many to many relationship. It doesn't even generate a class for the Company_Product table. Each Company has a Products collection, and each Product has a Companies collection.
However, if your associative table (Company_Product) has other fields (such as SKU, it's own Primary Key, or other descriptive fields like dates, descriptions, etc), then the EF modeler will create a separate class, and it does what you've already seen.
Having the class in the middle with 1:* relationships out to Company and Product is not a bad thing, and you can still get the data you want with some easy queries.
// Get all products for Company with ID = 1
var q =
from compProd in context.Company_Product
where compProd.CompanyID == 1
select compProd.Product;
True, it's not as easy to just navigate the relationships of the model, when you already have your entity objects loaded, for instance, but that's what a data layer is for. Encapsulate the queries that get the data you want. If you really want to get rid of that middle Company_Product class, and have the many-to-many directly represented in the class model, then you'll have to strip down the Company_Product table to contain only the 2 foreign keys, and get rid of the SKU.
Actually, I shouldn't say you HAVE to do that...you might be able to do some edits in the designer and set it up this way anyway. I'll give it a try and report back.
UPDATE
Keeping the SKU in the Company_Product table (meaning my EF model had 3 classes, not 2; it created the Company_Payload class, with a 1:* to the other 2 tables), I tried to add an association directly between Company and Product. The steps I followed were:
Right click on the Company class in the designer
Add > Association
Set "End" on the left to be Company (it should be already)
Set "End" on the right to Product
Change both multiplicities to "* (Many)"
The navigation properties should be named "Products" and "Companies"
Hit OK.
Right Click on the association in the model > click "Table Mapping"
Under "Add a table or view" select "Company_Product"
Map Company -> ID (on left) to CompanyID (on right)
Map Product -> ID (on left) to ProductID (on right)
But, it doesn't work. It gives this error:
Error 3025: Problem in mapping fragments starting at line 175:Must specify mapping for all key properties (Company_Product.SKU) of table Company_Product.
So that particular association is invalid, because it uses Company_Product as the table, but doesn't map the SKU field to anything.
Also, while I was researching this, I came across this "Best Practice" tidbit from the book Entity Framework 4.0 Recipies (note that for an association table with extra fields, besides to 2 FKs, they refer to the extra fields as the "payload". In your case, SKU is the payload in Company_Product).
Best Practice
Unfortunately, a project
that starts out with several,
payload-free, many-to-many
relationships often ends up with
several, payload-rich, many-to-many
relationships. Refactoring a model,
especially late in the development
cycle, to accommodate payloads in the
many-to-many relationships can be
tedious. Not only are additional
entities introduced, but the queries
and navigation patterns through the
relationships change as well. Some
developers argue that every
many-to-many relationship should start
off with some payload, typically a
synthetic key, so the inevitable
addition of more payload has
significantly less impact on the
project.
So here's the best practice.
If you have a payload-free,
many-to-many relationship and you
think there is some chance that it may
change over time to include a payload,
start with an extra identity column in
the link table. When you import the
tables into your model, you will get
two one-to-many relationships, which
means the code you write and the model
you have will be ready for any number
of additional payload columns that
come along as the project matures. The
cost of an additional integer identity
column is usually a pretty small price
to pay to keep the model more
flexible.
(From Chapter 2. Entity Data Modeling Fundamentals, 2.4. Modeling a Many-to-Many Relationship with a Payload)
Sounds like good advice. Especially since you already have a payload (SKU).
I would just like to add the following to Samuel's answer:
If you want to directly query from one side of a many-to-many relationship (with payload) to the other, you can use the following code (using the same example):
Company c = context.Companies.First();
IQueryable<Product> products = c.Company_Products.Select(cp => cp.Product);
The products variable would then be all Product records associated with the Company c record. If you would like to include the SKU for each of the products, you could use an anonymous class like so:
var productsWithSKU = c.Company_Products.Select(cp => new {
ProductID = cp.Product.ID,
Name = cp.Product.Name,
Price = cp.Product.Price,
SKU = cp.SKU
});
foreach (var
You can encapsulate the first query in a read-only property for simplicity like so:
public partial class Company
{
public property IQueryable<Product> Products
{
get { return Company_Products.Select(cp => cp.Product); }
}
}
You can't do that with the query that includes the SKU because you can't return anonymous types. You would have to have a definite class, which would typically be done by either adding a non-mapped property to the Product class or creating another class that inherits from Product that would add an SKU property. If you use an inherited class though, you will not be able to make changes to it and have it managed by EF - it would only be useful for display purposes.
Cheers. :)

How Do I Create And Update A Many To Many Relationship With EF

I am using the Entity Framework with SQL Server. I have a many to many relationship between 2 tables. I have created a join table with just the primary key fields of the 2 tables. In the designer, the 2 tables now have a navigation property to the other with return types of Collection of X where X is the other entity. So far, everything just as it should be. The setup looks correct.
Task TaskProducts Product
========== ============ =======
TaskID TaskID ProductID
Description ProductID Name
Not every task will have a product or products associated with it. What do I assign to the Products navigation property of the Task table when there is no associated Product for that Task?
Do I build up a EntityCollection collection with the Product entities and assign that to the Products navigation property on the Task entity when I do have Product entities?
When doing updates(adding, removing and changing) to the Products navigation property on the Task entity, do I work with it like any other collection? Are there any special things to look out for?
I would be interested in any help working with many to many relationships in the Entity Framework.
Edit(11/17/2009)
One thing I learned is that to a many to many relationship work with a join table, BOTH fields in the join table need to be marked as primary keys;
MSDN has good documentation on managing many-to-many relationships in the Entity Framework:
http://msdn.microsoft.com/en-us/library/bb738695.aspx
The prescriptive guidance for inserts is to call the "Add" method on the entity collection and specify the related object (versus setting the Value property on the entity reference for a one-to-many relationship.)
Updates are handled just like any other EF update... load the desired object, set the changed properties and call SaveChanges on the context.
Deletes are handled the same as well, call DeleteObject on the context and then SaveChanges.