in relation many to many is included a lot of objects - c#

I have a many to many relation between two tables in my database, so in my edmx model I have only two tables, no the intermediate table. This tables are Movies and Genres.
When I search for some movies, I get also the related entities, so with eager loading I populate the collection Genres of my entities Movies. Is what I want.
The problem is that when in the result has more than one movie, the collection Genres of the entities MOvies are populated, but also the collection Movies of the entities Genres are populated. So when I send to the repository one movie to be updated, if I attach the the entity to the context, I attach this movie and all the movies that have the same genres that the movie that I want to update. This is because in the genres of the entities are included the movies that are of the same genres than the movie that I want to update.
So if in my first search I get a lot of movies, when I want to update one movie I send a lot of entities that I don't need to seed, so it is a lot of traffic in the network.
is there any way that when I search for results the collection of movies in the genres entities are not populated? Because I only populate the related entities of my main entity, movies, not all of them.
I am using SQLite and EF 4.4; and I try to find the mergeOption to disabled the tracking of the genres, but I don't find it.
Thanks.

When you are designing entities and relationships (logical design), you can describe a many-to-many relationship between two entities. When you need to implement these entities and their relationship in a database (physical design), you can't do it with only two tables; you really need an intermediate table to express the relationship.
A one-to-many relationship between two entities only needs a table for each entity (simple foreign key relationship). So, if your genres table was simply a list of genres for a given movie, it would be a one-to-many (movie as parent, genres as child); that would work.
However, since you've described genres to be in a many-to-many relationship with movies, it suggests that genres is to be used to supply a sort of "pick list" i.e. one row in genres is not related to any specific row in movies, but could be related to any movie (and vice-versa). To make this relationship work, you need an intermediate table, let's call it "moviegenres" which need only contain two columns - a foreign key relating to movies' primary key, and a foreign key relating to genre's primary key. This table is actually expressing your many-to-many relationship, and assigning genres to movies is then effected by adding rows to "moviegenres".
Before you can consider any issues with how your data is populating, you need to resolve the logical-to-physical design issue first.

Related

How can I explore EF relationships and models at runtime?

I have a model call "Customer" which is to be linked to several other models (tables) in Entity Framework. When deleting the said Customer, I need to show all the related records and their counts and finally list all the records before allowing the user to delete the customer.
For example I might say this Customer is related to : Orders (1), Order_Items (5) where a customer is directly linked to an Order, and then an Order is linked to Order Items, but deleting the Customer will impact records in both the tables.
Is there a way to do this in .net dynamically or will I need to have a static view where I update all this info every time I make changes to the model and relationships?

Entity Framework with many to many relationship generetad tables

Here's my question. I have 2 models (Person, Event) and with EF and modelbuilder I generate a booking table (with IdPerson and IdEvent as properties).
So in my DB it's correct, I have 3 tables (Person, Event and Booking) with many to many relationship. But I have only 2 models in Visual Studio (Booking doesn't exist because of the self-generated table).
With my Controller I want to write an action for the Person to suscribe to an event and I have to write on my table Booking on the DB but it doesn't exist as a model so I can't do that .
How should I proceede?
Should I create a Booking model and delete my modelbuilder?
When you are using ORMs like EF, you can sit back and let the ORM manage these middle tables.
You can use
person.Events.Add(event)
or
event.People.Add(event)
and EF handles all and inserts a row with personId and eventId in that table.
Here you can find a complete sample:
http://blogs.msdn.com/b/wriju/archive/2011/05/14/code-first-ef-4-1-building-many-to-many-relationship.aspx
I assume this is a model first approach.
The reason for having only 2 objects is that, by default, EF does not create objects for joint tables. What it does create is Navigation Property (Entity Framework - Navigation Property Basics). In one-to-many scenario, a navigation property inside a parent object contains a collection of entities in a foreign / child table. In many-to-many scenario, navigation properties of each entities will simply contain collections of its other entities.

Entity Framework Linq query unrelated child tables

I am using Entity Framework 6.1.3 to generated the entities and data model.
If I have two tables: Orders -> OrderDetails, with a relation between them (OrderId), then I can get all the orders and related OrderDetails with the following query
dbContext.Order().Include(a => a.OrderDetails);
But if I created a view (vOrder) for Orders, then there is no direct relation between vOrder and OrderDetails in the model, though I can link them together with joins on OrderId. How could I still get all the data from vOrder and related OrderDetails. The following query doesn't work unless I add all the navigation properties manually.
dbContext.vOrder().Include(a => a.OrderDetails);
Is there a simple LINQ query to accomplish the intended query?
Thanks for your help.
Do a manual join and return an anonymous object that contains both.
Something like:
dbContext.vOrder
.GroupJoin(
dbContext.OrderDetails,
v=>v.orderid,
od=>o.orderid,
(v,od)=>new {v=v,od=od});
Of course, you could just add the appropriate naviation properties on to vOrder and do exactly what you said.
Why not just include more columns in the view (or create another view that has all the required data, if you don't want to modify the first one)?

How to manually load related entities in a N:N relationship?

I am using EF5 and when the the relationship is 1:N, if I want to load related entities I do the following:
With T-SQL I load from database the main entities with a T-SQL like that:
select *
from MainEntities
where ...
with T-SQL I load the related entities
select *
from RelatedEntities
where IDMainEntity IN (---)
At this point EF populate the property navigation of the main entities with the related entities. Also, in the local property of the type of each entity in the dbContext I have all the entities of each type.
However, if i do the same with a N:N relationship, I don't have the entity of the middle table of the relation, and when I execute the queries I have in the local of the dbContext the entities of each type, but the property navigation is not populated.
I would like to know why and if it exists some alternative.
I use this way because I want to use T-SQL for create dynamic queries. If I use eager loading I don't have the same flexibility to dynamic queries than when I use TSQL, and it is less efficient. If I use explicit loading I to do N additional queries, one of each record in the results of the main entity With my way, I only one additional query, because I get all the related entities at once. If I use lazy loading I have the same problem, N additional queries.
Why EF does not populate the related properties when the relation is N:N?
Thanks.
The feature you are talking about is called Relationship Span or Relationship Fixup and indeed - as you have noticed - it does not work for many-to-many relationships. It only works if at least one end of the association has multiplicity 1 (or 0..1), i.e. it works for one-to-many or one-to-one relationships.
Relationship Span relies on an entity having a foreign key. It doesn't matter if it has an explicit foreign key property (foreign key association) or only a foreign key column in the corresponding database table without a property in the model (independent association). In both cases the FK value will be loaded into the context when the entity gets loaded. Based on this foreign key value EF is able to figure out if a related entity that has the same primary key value as this FK value is attached to the context and if yes, it can "fixup the relationship", i.e. it can populate the navigation properties correctly.
Now, in a many-to-many relationship both related entities don't have a foreign key. The foreign keys are stored in the link table for this relationship and - as you know - the link table does not have a corresponding model entity. As a result the foreign keys will never be loaded and therefore the context is unable to determine which attached entities are related and cannot fixup the many-to-many relationship and populate the navigation collections.
The only LINQ queries where EF will support you to build the correct object graph with populated navigation collections in a many-to-many relationship are eager loading...
var user = context.Users.Include(u => u.Roles).First();
...or lazy loading...
var user = context.Users.First();
var rolesCount = user.Roles.Count();
// Calling Count() or any other method on the Roles collection will fill
// user.Roles via lazy loading (if lazy loading is enabled of course)
...or explicit loading with direct assignment of the result to the navigation collection:
var user = context.Users.First();
user.Roles = context.Entry(user).Collection(u => u.Roles).Query().ToList();
All other ways to load the related entities - like projections, direct SQL statements or even explicit loading without assignment to the navigation collection, i.e. using .Load() instead of .Query().ToList() in the last code snippet above - won't fixup the relationship and will leave the navigation collections empty.
If you intend to perform mainly SQL queries rather than LINQ queries the only option I can see is that you write your own relationship management. You would have to query the link table in addition to the tables for the two related entities. You'll probably need a helper type (that is not an entity) and collection that holds the two FK column values of the link table and probably a helper routine that fills the navigation collections by inspecting the primary key values of the entities you find as attached in the DbSet<T>.Local collections and the FK values in the helper collection.
To add on #Slauma answer:
I faced the same problem recently, getting frustrated that the navigation property is not being set after calling Query().Where().Load(), although I can see that the objects are loaded into the DbContext.
I needed the collection to be part of my main object and use it as you would any other navigation property and not just manage a separate collection, so I did this:
project.Labels = this.Context
.Entry (project)
.Collection (p => p.Labels)
.Query ()
.Where (l => l.CreateUserName == this.UserId)
.ToList();
The problem with this is that EF thinks I added new relationships, which I can't blame it, but it is not what I wanted. As a result, when trying to save the Project object I got an exception when EF tried to insert the relationship into the link table because a row with the same key (projectId + labelId) already exists.
So, the final was to reset the state of the relationships between the project and the labels:
foreach (Label l in project.Labels)
{
((System.Data.Entity.Infrastructure.IObjectContextAdapter)this.Context.AsDbContext ()).ObjectContext.ObjectStateManager.ChangeRelationshipState<Project> (project, l, p => p.Labels, EntityState.Unchanged);
}
After that I was able to use the Labels property just like any other navigation property, not caring that behind the scenes it's a many-to-many relationship.

many-to-one with multiple columns

I have a legacy data base and a relation one-to-one between two tables. The thing is that relation uses two columns, not one. Is there some way to say in nhibernate that when getting a referenced entity it used two columns in join statement, not one?
I have a similar table structure
TaskProgress
ProgressId
TaskId
AssignmentId
UserId
Tasks
TaskId
AssignmentId
TaskName
Each task can be asigned in different assignments. That mean that unique task for task progress can be founded only by AssignmentId and TaskId fields.
I'm trying to use this:
References(x => x.Template)
.Columns()
.PropertyRef()
But can't get how to map join on multiple columns, any ideas?
I'm assuming from your use of PropertyRef in the sample code that the two columns do not form a composite primary key. If that's the case, then you're out of luck because property-ref can only accept one property. Judging by the comments in issue NH-1722, this functionality apparently available in Hibernate but has not been ported to NHibernate.
Update:
The schema you added looks like a many-to-many with additional data relationship between Task and Assignment. TaskProgress is the link table between Task and Assignment. If TaskProgress did not have the additional UserId field then you could model this as a simple many-to-many. Because the linking table has additional data it gets a bit more complicated.
Many-to-many with additional data is usually modeling by creating an object representing the linking table (TaskProgress) and modeling the relationship as two one-to-many relationships. That is, Task and Assignment have one-to-many relationships with TaskProgress. TaskProgress has properties for Task, Assignment, and User.

Categories

Resources