I have entities User and DiscussionThread and I need to create many-to-many relationship but I forgot to put a ICollection in User entity, so Code First created a one-to-many relationship.
I wonder if there is a way how to migrate this relationship to many-to-many. I tried following things, but nothing helps:
I added ICollection to User entity
I added modelBuilder.Entity().HasMany(t => t.NotificationSubscribedUsers).WithMany(u => u.SubscribedThreadNotifications) to configuration
I tried generate new migration (using Add-Migration), but migration is empty
No DB tables were created/updated and EF still uses a one-to-many relationship...
Related
I am developing for an existing application which uses a SQL database that is used by two applications. One uses Entity Framework to connect to the database. The other uses LINQ-to-SQL. The SQL database is designed so that there are some tables showing many-to-many relationships between rows in two tables. Entity Framework seems not to import these tables, apparently because it has some object-oriented idea for how many-to-many relationships ought to be represented. So far, the Entity Framework application has not needed to know about those tables, but now it should. I don't know how that works, and I am concerned that even if I learn about Entity Framework's exciting new way to represent these relationships, that it won't cooperate nicely with the other application or the database which is designed to use the many-to-many table.
I.e., there is a table of Foos, and a table of Bars, and then a table with Foo and Bar Ids that lists which Foos relate to which Bars, and I don't want to stop using this relationship table, particularly because there is another LINQ application that heavily uses this relationship table.
Questions:
If I learn to use Entity Framework's many-to-many system, will it use and update the many-to-many table that the other application uses?
If not, what is a good way to get Entity Framework to not ignore the many-to-many relationship table, so I can write code to use the existing table?
Yes, Entity Framework will manage your many-to-many tables for you. Pure link tables (that only have two foreign key columns) in EF are represented as relationships as opposed to POCO objects. The way this is done is that you tell EF that there is a relationship between two of your objects and that table X is where this relationship is stored. As an example in EF 4.1. which is what I'm currently using this is done like so:
modelBuilder.Entity<Foo>() //Let me tell you about Foo...
.HasMany(f => f.Bars) //The property in the Foo class that links to Bar objects is Bars
.WithMany(b => b.Foos) //The property in the Bar class that links to Foo objects is Foos
.Map(m => {
m.MapLeftKey("FooID"); //Name of the foreign key column in the link table for Foo
m.MapRightKey("BarID"); //Name of the foreign key column in the link table for Bar
m.ToTable("FooBar"); //Name of the link table
});
You can then make changes to this table by linking/unlinking objects in your code. You pretty much do something like
myFoo.Bars.Add(myBar); //Add a row to the link table
myFoo.Bars.Remove(myBar) //Delete a row from the link table
For a full implementation you should google your version of EF.
In case of link tables that contain extra columns (for example a creation date) they are represented by a POCO just like all the other tables. If you're really paranoid about EF's ability to manage your link tables you can force it to go this route by adding a unique id column to your pure link tables, but I'd definitely advice against it.
Think of it this way: EF has been around for a while now and has achieved a certain degree of maturity. Combine this with the fact that many-to-many relationships are not exactly rare in databases. Do you really think the designers of EF haven't dealt with your case?
I have a couple of entities, all inherits base entity with auditing and ID fields. In the configuration for each property I have absolutely same lines like:
this.HasKey(t0 => t0.Id)
.Map(m => m.ToTable("templates"))
.Property(x => x.Id)
.HasColumnName("id")
...................
Is there way to move this code to some kind of "base configuration" to not to write it for each entity?
All you'd need to do is to implement either Table-Per-Type or Table-Per-Hierarchy:
In Table-Per-Type your entities will be split into different tables, but all offshoot tables will have its PK be a FK to the base entity table.
In Table-Per-Hierarchy your entities will all be in one table, but EF will generate a discriminator to discern which object type the entity is actually a part of.
For a clearer example of this, check out the post at this site.
I've a problem mapping just one table from database, I add several tables using "Update model from Database" function through Visual Studio 2010 interface, and everyone works as expected except one table!
Looking at "Model Browser" I can see the table doesn't appear under "Entity Types" but it is present under section "ObjectEntity.Store", so my POCO Generator create an entity related and I can't try to add it again from database but I can't access it through context (like context.table_name).
Tha table doesn't have particular form, there are just two key fields
Could someone help me?
Thanks
I guess it is junction table for implementing many-to-many relation, isn't it? In such case it is correct behavior. EF will hide this table because it is not needed in object oriented approach where many-to-many association can be modeled directly without helper entity. You will see in your model that those two related entities are connected by line with * - * multiplicity and each entity will contain navigation property which is collection of related entities. By manipulation with entities in these collections you are creating or removing records in that hidden table. That is the way how you work with such relation in EF.
I have a data model as follows:
A Customer has Products and Payment Methods. Each Product can be assigned any or all of the Customer's Payment Methods, with one set as default.
Foreign Keys are:
Customer.CustomerId => Product.CustomerId
Customer.CustomerId => PaymentMethod.CustomerId
Product.ProductId => ProductPaymentMethod.ProductId
PaymentMethod.PaymentMethodId => ProductPaymentMethod.PaymentMethodId
I want to customise this model for presentation purposes, Customer to have a collection of Payment Methods and a collection of Products. Products to have a collection of ProductPaymentMethods which inherit from PaymentMethod.
I deleted the association between PaymentMethod and ProductPaymentMethod, added an inheritence from PaymentMethod to ProductPaymentMethod and deleted PaymentMethodId from ProductPaymentMethod.
This is now my model:
When I save the model or build the project I get 2 errors:
Error 3002: Problem in mapping
fragments starting at line
226:Potential runtime violation of
table ProductPaymentMethod's keys
(ProductPaymentMethod.ProductPaymentMethodId):
Columns
(ProductPaymentMethod.ProductPaymentMethodId)
are mapped to EntitySet
PaymentMethods's properties
(PaymentMethods.ProductPaymentMethodId)
on the conceptual side but they do not
form the EntitySet's key properties
(PaymentMethods.PaymentMethodId).
and
Error 3003: Problem in mapping
fragments starting at line 226:All the
key properties
(PaymentMethods.PaymentMethodId) of
the EntitySet PaymentMethods must be
mapped to all the key properties
(ProductPaymentMethod.ProductPaymentMethodId)
of table ProductPaymentMethod.
What am I doing wrong?
EDIT: Having done some further Googling, I have found several solutions, most of which don't quite fit this scenario. Most talk about inheritance requiring a 1-1 not 1-many relationship. However, because of the Customer to Product 1-many relationship, the model requires a 1-many between PaymentMethod and ProfilePaymentMethod. Is it not possible to do what I am attempting?
My only answer to this so far is to have some manually created POCO classes for presentation and a Mapper class to turn my data entity into a presentation entity
We have legacy database and we map the new objects and props to the old tables and columns. So far so good. We have many-to-many relation which was mapped successfully. The intermediate table contains additional data. When we try to map the intermediate table to an object we get exception that the mapping is already defined. If we remove mapping from any side of the relation we get error that table is missing (ofc, we expect just that). I can do that easily with NHibernate and I am starting to think that EF is missing really really many features. So, please, tell me I am wrong and we can do that with EF.
Best regards
EDIT: here is a dummy sample which fails.
class User
{
public ICollection<User> Followers{get;set;}
}
class UserRelation
{
public User User{get;set;}
public User Follower{get;set;}
public DateTime CreatedOn{get;set;}
}
user mapping
modelBuilder
.Entity<User>()
.HasMany<User>(user => user.Followers)
.WithMany()
.Map(m =>m.MapLeftKey("user_id").MapRightKey("follower_id")
.ToTable("user_follower"));
user relation mapping
modelBuilder
.Entity<UserRelation>()
.ToTable("user_follower");
modelBuilder
.Entity<UserRelation>()
.HasOptional<User>(f => f.User)
.WithRequired().Map(m => m.MapKey("user_id"));
modelBuilder
.Entity<UserRelation>()
.HasOptional<User>(f => f.Follower)
.WithRequired().Map(m => m.MapKey("follower_id"));
modelBuilder
.Entity<UserRelation>()
.Property(entity => entity.CreatedOn)
.HasColumnName("created_on");
Exception
Schema specified is not valid. Errors:
(67,6) : error 0019: The EntitySet 'UserUser' with schema 'dbo' and table 'user_follower' was already defined. Each EntitySet must refer to a unique schema and table.
Edit2: Here is another example of this model: http://learnentityframework.com/LearnEntityFramework/tutorials/many-to-many-relationships-in-the-entity-data-model/
Direct many-to-many mapping is available only if junction table contains just foreign keys. If you want to expose other properties in junction table you must map it to separate entity and mapt two one-to-many relations from former entities used in many-to-many.
I'm actually not able to write you the code because I don't understand your example.
Try only (don't map Many-to-many in User):
modelBuilder.Entity<UserRelation>
.HasRequired(r => r.User)
.WithMany(u => u.Followers);
modelBuilder.Entity<UserRelation>
.HasRequired(r => r.Follower)
.WithMany();
EF maps many-to-many relationships as properties of the related objects.
So, let's say you have Cars and Drivers that are related m-to-n. In your EF model, you will see that each Car object has a Drivers collection as a property, and each Driver object has a Cars collection as a property.
That is how m-to-n relationships are modeled in EF.