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.
Related
I have created a view "Supplier" that shows columns from a table "T_ADDRESS". The view is declared as (I know, the '*' is a no-go in views)
create View Supplier as
select * from T_ADRESSEN where IsSupplier = 1
In EF, I want to use the view as it is more readable than the ugly "T_ADRESSEN". So far so easy.
Now comes the tricky part (for me). The table T_ADDRESS has a self referencing foreign key "MainAddressId" which points to T_ADDRESS.
Creating a DB-first (or CodeFirst from DB) will create the FK relationship for the table T_ADDRESS (and the navigational properties), but not for the view 'Supplier'. Of course not: EF does not know anything about the FK relationship (although the view exposes the same columns).
Now I tried to use the 'ForeignKey' and 'InverseProperty' attributes in my code first model on the Supplier-class but this gives me an ModelValidationException. Also clear: There is no such FK-relationship.
How can I tell EF to treat a field just like a foreign key although the constraint does not exist?
What I am trying to do is to have 'Suppliers' in my EF model (as a subset of T_ADDRESS). If there is another way to do it, I would be happy to receive a hint.
You can't define ForeignKey and InverseProperty on a view. In your case, you need to use that ugly T_ADRESSEN table and use [AutoMapper][1] to map it the to the DTO class. In your case, T_ADRESSEN is the context table and Supplier is your DTO class.
with AutoMapper you can do something like this:
var ugly = context.T_ADRESSEN.Where(e=>e.IsSupplier ==1);
var suppliers = mapper.Map<IEnumerable<Supplier>>(ugly);
where mapper is IMapper interface defined in AutoMapper.
Sometime one should figure out that the DTO mapping technique as a replacement to the traditional database view.
I am trying to implement TPH recursive relationship on one of the concrete types using Entity Framework 5 and Database first approach.
I have conceptual model, and table structure like this:
Also, i have recursive relationship like this in my database table.
ALTER TABLE [dbo].[BaseType]
WITH CHECK ADD CONSTRAINT [FK_BaseType_DerivedType]
FOREIGN KEY([Derived1RecursiveId])
REFERENCES [dbo].[BaseType] ([Id])
When i update model with this relation i get diagram like this:
My question is:
How can i implement a recursive relationship in a database so that when model is updated from database (refreshed), recursive relationship is set on DerivedType1?
It is not possible for the EF model to automatically deduce that the Derived1RecourseiveId is part of the Derived1 class. But you can move the association in your edmx file manually. Just move the foreign key column, delete the association on your base table and recreate it on the derived. Once moved it will stay in your derived type even if you do a model refresh.
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.
I am making an library which will be used to talk with database using Entity framework. For different workflows I need different tables from database. So I decided to have separate models for separate workflows. But for some workflows one entity is used in multiple models. Now for one model I have modified my entity class (changed some getters/setters and added custom functions). But when I create new model for different workflow then model will generate entity with default names. I have to edit it again and code will be duplicated. Both are in different namespaces (one is Model1Namespace, second is Model2Namespace).
So what I exactly need is that if entity is used in different classes a single code is used (no duplicate code). What are the best practices? Do EF provide us something or we need to implement it ourself?
Example:
Database tables: TableA, TableB, TableC, TableD
Models: Model1 -> TableA, TableB
Model2 -> TableA, TableC,
Model3 -> TableC, TableD
Edit:
I have a database containing 4 tables (TableA, TableB, TableC, TableD). I create a Entity data model of the database which contains TableA and TableB. In entity designer view I modified names of properties of TableA Entity so that they are readable. Now I create another model which contains TableA and TableC. Now here I have to rename all properties of TableA again. Now this is repeat work. Now if I add some custom action to my Entity for Model1 then I have to write (copy) them to new Model2 Entity as well. I need to avoid this. As I really don't know how many models I will create. And if I have to do this stuff again and again then it will take lot of time.
I am stuck here.
Is it possible to map data from 2 different tables to 1 entity in Entity Framework 4.
I have a bunch of employees in one table, and in the other I have som project information.
I would like to combine these 2 tables in one Entity, and keep the tracking features etc., is that possible?
I do not want to use a function import, but do it solely through the Entity Model.
Can anyone help - when I try to do it, i get the following error all the time:
Error 3024: Problem in mapping fragments starting at line 2354:Must specify mapping for all key properties (MyProjectTable.PSInitials, MyProjectTable.ProjectID) of the EntitySet MyProjectTable.
Both key are mapped to their respective tables.
The new Entity are made with MyProjectTable as the basetable.
The relation between the 2 tables is a 1-*
Hope you can help.
/Christian
You cannot map two tables with a one-to-many relationship to one entity. If you don't want projecting the results into one object in code, consider creating a view and mapping it instead.
According to http://msdn.microsoft.com/en-us/library/bb896233.aspx
You should only map an entity type to
multiple tables if the following
conditions are true:
The tables to which you are mapping share a common key.
The entity type that is being mapped has entries in each
underlying table. In other words,
the entity type represents data
that has a one-to-one correspondence between the two
tables; the entity type represents an
inner join of the two tables.
The reasons for doing this are quite straightforward - for example, a table of data points that all have one of five 'types'. Obviously the 'type' will be a separate table for the sake of normalisation, but from an application point of view (working with the data) it makes more sense to have all properties in a single entity.
So we can't do this with Entity Framework - a supposed Object-Relational-Mapper. What, then, is the point of using such a framework?