How can I join two tables by a foreign key table in Entity Framework? - entity-framework

I am trying to join two tables by a foreign key table in linq.
The two tables are
Items and Classes, and the foreign key table is ItemClasses (ItemId, ClassId).
My context does not have a DBSet for the foreign key table, and when I try to add it I get a model creation error.
When I saw the error, I noticed that this code referred to the foreign key table
modelBuilder.Entity<Classes>()
.HasMany(e => e.Items)
.WithMany(e => e.Classes)
.Map(m => m.ToTable("ItemClasses").MapLeftKey("ClassId").MapRightKey("ItemId"));
So it looks like I should be able to refer to the items through the class, but how do I join the tables?
I'd like to do something like this
query = from ig in myCtx.Items.AsNoTracking()
//join di in myCtx.ItemClasses.AsNoTracking() on ig.Id equals di.ClassId
join c in myCtx.Classes.AsNoTracking() on di.ClassId equals c.Id
join dd in myCtx.SalesAssociates.AsNoTracking() on dd.Id equals ig.SalesAssociateId
How do I do joins when the fk table is not in my context, but is referred to in one of the tables?

First, you have a configuration error. With HasMany / WithMany you are actually configuring the automatic "link" table, so
m.ToTable("Classes")
should be
m.ToTable("ItemClasses")
or how exactly you want that table to be named in the database.
Second, when working with EF, it's always preferred to use navigation properties rather than joins. In case of many-to-many relationship with auto link table, using navigation properties is mandatory. EF will produce the necessary joins for you.
So instead of join your would use something like this:
query = from ig in myCtx.Items.AsNoTracking()
from c in ig.Classes
...

Related

Entity Framework - How to Insert to table with foreign keys without retrieving foreign table rows first

I'm having a hard time finding the exact answer to this question, so my apologies if this is redundant.
So I have 3 tables defined such that:
Person :PersonId, FirstName, LastName
Company: CompanyId, CompanyName
Order: OrderId, PersonId, CompanyId
On the Order table, there is a foreign key defined on the PersonId and CompanyId columns, thus, my Order entity class generated by EF has a navigation properties of type Person (not PersonId) and Company.
So, to insert into the Order table, I first need to query the person and company tables to get the person and company entities. Then I can construct the Order object using the Person and Company entities and save it to the db.
In my scenario, I am being passed a PersonId and CompanyId.
In classic SQL I would just do INSERT INTO Order Set (CompanyId, PersonId) - 1 database call. But with EF, I have to do 3 db calls. This seems like overkill.
Is there any way around this?
PS - I'm using EF 6. I know I could generate an expression and make it single call..but that would still yield two subselects.
You can just include foreign key properties in addition to the navigation properties and then set them using the ids you have. If you do this will not have to go to the database to get related entities for just a sake of setting the relationship.

EF4 one to one on code first and existing database and without foreign key

I am trying to map an existing db to POCO classes using the fluent API. Everything works fine with one to many and many to many relationships but one to one fails with the gazillions of options I tried.
The sql tables are simple, Agent with AgentID as PK and AdditionalAgentInfo with AdditionalAgentInfoID as PK and a column AgentID. Agent does NOT have an AdditionalAgentInfoID, but I added this in my test db to see if this will solve it with no luck.
All the posts point out to do:
pModelBuilder.Entity<Agent>()
.HasOptional(u => u.AdditionalAgentInfo)
.WithRequired(x => x.Agent);
pModelBuilder.Entity<AdditionalAgentInfo>()
.HasRequired(u => u.Agent)
.WithOptional(x => x.AdditionalAgentInfo);
My context loads but Agent.AdditionalAgentInfo is always NULL. Looking into the profiler, the sql tries to join on the wrong column:
FROM [dbo].[AdditionalAgentInfo] AS [Extent1]
WHERE [Extent1].[AdditionalAgentInfoID] = #EntityKeyValue1
it should be :
FROM [dbo].[AdditionalAgentInfo] AS [Extent1]
WHERE [Extent1].[AgentID] = #EntityKeyValue1
So I tried to add Map(x=>x.MapKey("AgentID") but than I get duplicate columns error.
What am I missing ?
That is because EF supports only shared PK one-to-one mappings. The AdditionalAgentInfo PK should also be a FK to Agent table. Otherwise you have to map it as one-to-many relationship and ignore the many end property.

Map parent child relationship in EntityFramework on top of existing database

i need to map some parent children relationship on top of a legacy database, the problem is how the tables are structured.
tableA
id
name
tableB
id
tableA_parentId
tableA_childId
As showed I have two foreign key from tableA to tableB
Is there a way to map this relationship with EF i'm using the code first approach and have a configuration class per table

What 'possible data inconsistency' is entity framework worried about in a 'foreign key participating in multiple relationships' situation?

Suppose the following database schema:
Table A: AId (PK)
Table B: BId (PK)
Table C: CId (PK)
Table AB: AId, BId (composite PK, FKs to A and B), Data
Table BC: BId, CId (composite PK, FKs to B and C), Data
Table ABC: AId, BId, CId, Data
In the database, ABC has two FKs: one to AB on AId and BId, and one to BC on BId and CId.
Use the EF Designer and attempt to create a Model from this database.
If you have Include foreign key columns in the model checked, it works; but having FK Columns in the model isn't very nice.
If you have Include foreign key columns in the model unchecked, only one of the FKs from ABC will be successfully mapped. To see what went wrong, you have to view the .edmx xml (thanks Craig!) and you see this error:
warning 6037: Foreign key constraint 'FK_ABC_BC' has been omitted from the storage model. Column 'BId' of table 'Model.Store.ABC' is a foreign key participating in multiple relationships. A one-to-one Entity Model will not validate since data inconsistency is possible.
I've read the only other mention of this problem I can find on SO, and I don't think this is the same problem. I can't see anything wrong at a database design level. I'm going to work round this for the time being by imposing surrogate keys on AB and BC, but what I'd really like to know is:
What possible data inconsistency is EF worried about happening here, if it created a model to match the database?
And is there anything I can do to persuade it that everything's going to be OK?
My opinion is that EF is too clever in this scenario and it prevents you from using entity where you can assign only one relation and make the entity non-savable because relation to second entity will not exists.
There is also possibility that EF has some internal problem with tracking state of independent associations if more than one association is based on the same foreign key column but that is just another guess. Generally database features used to map EF features cannot be shared among multiple constructions. The only exceptions I can think about now are primary keys and in their own way discriminator columns.
I would like to mention that I don't like this type of relations in database at all.

Entity Framework Association with Non Key fields

Is it possible to create associates b/t 2 non-key fields in the Entity Framework?
Example: Take the 2 tables in a legacy application (i.e. keys/structure cannot change)
Order (
OrderId : int : PK
OrderNo : varchar
)
OrderDetails (
DetailRecordId : int : PK
OrderNo : varchar
)
In the Entity Framework, I want to create an association b/t Order and OrderDetails by the OrderNo field, which is not a primary key on either table or a FK relationship in the database.
This seems to me as not only should it be easy to do, but one reasons to use something like EF. However, it seems to only want to allow me to create associations using entity keys.
The Entity Framework allows you to claim that columns are keys and that FK constraints exist where none actually exist in the database.
That is because the SSDL (StorageModel part of the EDMX) can if necessary be manipulated by you and lie about the database.
The EF will then interact with the database as if the keys and foreign keys really do exist.
This should work, but all the normal caveats about referential integrity apply.
See my Entity Framework Tips
Hope this helps.
The problem with using non-key fields to define relationships is that the keys are not guaranteed to be properly navigatable. That could lead to a situation where you have a one to one relationship between two entities where there are more than one possible rows that fufill the relationship.
...when relating data from a database, the relationships should always be based on keys. The keys enforce the referential integrity.
One more workaround:
create view vOrder which will not include PK and create Entity from it.
Set PK in this entity to OrderNo
Now you will be able create association