Entity Framework and 2 associations on the same table. Is it possible? - entity-framework

I have 3 tables:
Product
Category
ProductCategory
when doing entity framework Database First it creates 2 classes.
Product {
int ProductId
virtual ICollection<Category>
}
Categories {
int CategoryId
virtual ICollection<Product>
}
this is great.
I want to create a new property on the table ProductCategory, for example, CreateDate
So I will have one more entity (ProductCategory) with the CreateDate property :
Product
Category
ProductCategory
So far so good, but it removes the navegability from Product to Category and creates the navegability from Product to ProductCategory and then to Category.
I manually changed in model browser and added a new navegability that create the previous behaviour in classes so I ended up with what I want :
Product {
int ProductId
virtual ICollection<Category>
ProductCategory
}
Category {
int CategoryId
virtual ICollection<Product>
ProductCategory
}
ProductCageory {
Product
Category
}
all compiles fine, but when I run the code and update an entity the following error raises :
error 3034: Problem in mapping fragments starting at lines 2445, 2452:
Two entities with possibly different keys are mapped to the same row.
Ensure these two mapping fragments map both ends of the AssociationSet
to the corresponding columns.
Is there any way to keep my desired scenario (Both navegabilities from Product to ProductCategory and to Category and vice versa) ? If so, how can I get rid of this error ? am I missing mapping something ?
Tryied to be the less verbose possible but I don't mind adding more information or updating the question if anything missing so don't hesitate to ask for more info. Thanks.
Extra: Using MySql 6.8.3 with Entity Framework 6 (latest minus version) Database First using DbContext and T4.
updated:
This is what I want to have :
public class Product
{
public int Id { get; set; }
public ICollection<ProductCategory> ProductCategories { get; set; }
public ICollection<Category> Categories { get; set; }
}
public class Category
{
public int Id { get; set; }
public ICollection<ProductCategory> ProductCategories { get; set; }
public ICollection<Product> Products { get; set; }
}
public class ProductCategory
{
public int Id { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}

If you want to have many to many relationship that can navigate both ways, you should have as follow.
public class Product
{
public int Id { get; set; }
public ICollection<ProductCategory> ProductCategories { get; set; }
[NotMapped]
public ICollection<Category> Categories
{
get { return (ProductCategories ?? new ProductCategory[0]).Select(pc => pc.Category).ToArray(); }
}
}
public class Category
{
public int Id { get; set; }
public ICollection<ProductCategory> ProductCategories { get; set; }
[NotMapped]
public ICollection<Product> Products
{
get { return (ProductCategories ?? new ProductCategory[0]).Select(pc => pc.Product).ToArray(); }
}
}
public class ProductCategory
{
public int Id { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}

Related

Merge Key constraint with Entityframework

I am a .NEt student trying to build a simple pizza webbshop. I am using Entityframework to build the database. The errormessage I get is this:
The MERGE statement conflicted with the FOREIGN KEY constraint "FK_Products_Categories_CategoryID". The conflict occurred in database "TomasosPizzeria", table "dbo.Categories", column 'CategoryID'.
The statement has been terminated.
I have googled and tried to solve this pne alone by renaming the properties back and forth. Here are my classes:
public class Product
{
public int ID { get; set; }
public string ProductName { get; set; }
public int ProductPrice { get; set; }
public string Ingridients { get; set; }
//--
public List<OrderDetail> OrderDetails { get; set; }
[ForeignKey("Categories")]
public int CategoryID { get; set; }
public virtual Category Categories { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
List<Product> Products { get; set; }
}
I am using a DbInitializer to set som test values. I have had problems giving the product object a category with the corresponding value.
var categories = new Category[]
{
new Category{CategoryName="Pizza"},
new Category{CategoryName="Pasta"},
new Category{CategoryName="Sallad"},
};
var products = new Product[]
{
new Product{ProductName="Äcklig Calzone", Ingridients="Gamla tomater, möglig ost, trötta oliver, Unken skinka", ProductPrice=150},
new Product{ProductName="Italiensk skit", Ingridients="Proscutti, halvfärdig mozzarella, trötta oliver, skämd vattnig proscutti", ProductPrice=250},
new Product{ProductName="La bussola", Ingridients="Äckliga tomater, giftiga räkor, levande musslor, rutten skinka",CategoryID = 2,<--Here-- ProductPrice = 105 }
};
foreach (Product s in products)
{
context.Products.Add(s);
}
context.SaveChanges();
I am thankful for all the help I get. Please tell me if you wish to see any more of my code.
Solved it by giving CategoryID to the two other products.

If Exists Dont Add Data Entity Framework Many-To-Many

I have these two Models the logic is here One Post can have multiple Categories.
public class Post
{
public Post()
{
this.Categories = new HashSet<Category>();
}
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ShortDescription { get; set; }
public string PostImage { get; set; }
public string Thumbnail { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? PublishedDate { get; set; }
public string CreatedBy { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
I have three static categories.
When I am trying to add new post its multiplexing CategoryTable creating new categories with same name ,And Mapping Them in to CategoryPostsTable.
The problem is here i want to map that data with existing categories. I dont want to add new category with same name.
I am using Repository Pattern how should i control that ? Is EF has some solution for that ?
I assume you have code like:
var post = new Post();
post.Categories.Add(cat);
context.Posts.Add(post);
...where cat is a Category object representing an existing category.
The latter Add method (DbSet.Add) doesn't only mark the received entity as Added but all entities in its object graph that are not attached to the context. So cat will also be marked as Added if it wasn't attached yet.
What you can do is
context.Entry(cat).State = System.Data.Entity.EntityState.Unchanged;
Now EF will only create the association to the category, but not insert a new category.

Mapping Many to many in Entity framework

simply I ask this How to Map , How to ProductCustomer in the sample ??
public class ProductCustomer
{
public virtual Product Product { get; set; }
public virtual Customer Customer { get; set; }
}
and about Product and Customer :
public class Customer
{
public int Id { get; set; }
public string CustomerName { get; set; }
}
public class Product
{
public int Id { get; set; }
public string ProductName { get; set; }
public decimal Amount { get; set; }
}
thanks!
You don't need to create the ProductCustomer object.
In EF, you create your Customer and Product, and then you create collections to each. This will automatically create the proper link tables.
public class Customer
{
public int Id { get; set; }
public string CustomerName { get; set; }
public virtual List<Product> Products {get;set;}
}
public class Product
{
public int Id { get; set; }
public string ProductName { get; set; }
public decimal Amount { get; set; }
public virtual List<Customer> Customers {get;set;}
}
This is only the case, however, if your link table has no payload (has no additional data). If it does, then you will need to create the link table as an entity similar to what you originally did, but you add 1:many links in your product and customer classes to the link entity. You then have to modify your queries to query through the link table.

Entity Framework Code-First One-To-One Relationship

I have two database tables:
Customers
CustomerId (PK)
Name
...
CustomerSettings
CustomerId (PK)
Setting1
Setting2
...
Is it possible to have these classes using code-first? If so, what is the fluent mapping?
public class Customer
{
public int CustomerId { get; set; }
public int Name { get; set; }
public CustomerSetting CustomerSetting { get; set; }
}
public class CustomerSetting
{
public int CustomerId { get; set; }
public int Setting1 { get; set; }
public int Setting2 { get; set; }
public Customer Customer { get; set; }
}
I personally don't like one-to-one tables. After all, why not just add the setting columns to the customer table? Unfortunately, this is what I need to develop against. I can't figure the correct code-first mappings for such a scenario. Thanks for your help.
If you are going for code first and want to have both Customer And CustomerSettings classes,
but only a single table for both, as your post suggests ,
I would use complex types.
see a good example here:
http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx
So , your object model should look like this (I've not tested it):
public class Customer
{
public Customer()
{
CustomerSetting= new CustomerSetting();
}
public int CustomerId { get; set; }
public int Name { get; set; }
public CustomerSetting CustomerSetting { get; set; }
}
[ComplexType]
public class CustomerSetting
{
public int CustomerId { get; set; }
public int Setting1 { get; set; }
public int Setting2 { get; set; }
public Customer Customer { get; set; }
}
Your model classess are correct, if you want you can add this to your model builder to specify which table is the "main one":
.Entity<Customer>()
.HasOptional(c => c.CustomerSetting)
.WithRequired(u => u.Customer);

EF 4 CTP 5 Complex query

I have a model like the following:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public DateTime DateTime { get; set; }
public Customer Customer { get; set; }
public ICollection<OrderLine> OrderLines { get; set; }
}
public class OrderLine
{
public int Id { get; set; }
public Product Product { get; set; }
public int Price { get; set; }
public int Quantity { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
I am using this infrastructure.
My aggregate roots are Customer, Order, Product. I did not include the mappings here as they are straight forward.
var customers = unitOfWork.Customers.FindAll();
var orders = unitOfWork.Orders.FindAll();
var products = unitOfWork.Products.FindAll();
var query = ......
Using LINQ, how would you select all customers that have orders for products in the "Beverages" category?
All samples I have seen on the web are very basic queries nothing advanced.
i found http://msdn.microsoft.com/en-us/vbasic/bb737909
May be your query should look like:
from c in unitOfWork.Customers
join o in unitOfWork.Orders on o.Customer = c
join ol in unitOfWork.OrderLines on ol.Order = o
where ol.Product.Category.Name == "Beverages"
select c
And it is necessary to add all parent-object-properties
This might work or not:
from customer in customers
where customer.Orders.Any(
o => o.OrderLines.Any(l => l.Product.Category.Name == "Beverages")
select customer
(I'm assuming you forgot the relationship between Product and Category)