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
Related
I am using Spring data JPA(Hibernate).
I am trying to join my tables (Table A & Table B) but on Non-Primary Columns. Is it possible to actually do that? I am trying to use referenceColumnName, but it seems to not working, giving error :
Cannot set int to Integer.
When I am removing referenceColumnName, then it is working but obviously it is joining with Primary Key. Also in case of One-to-one Bidirectional, where should I place mappedBy & JoinColumn?
The annotation #JoinColumn indicates that this entity is the owner of the relationship (that is: the corresponding table has a column with a foreign key to the referenced table), whereas the attribute mappedBy indicates that the entity in this side is the inverse of the relationship, and the owner resides in the "other" entity.
Regarding the other question of using joining tables on Non-Primary columns, there are plenty of threads why don't you go through. for example
Does the JPA specification allow references to non-primary key columns?
I am struggling with the way entity framework handles join tables, specifically because entity framework requires that a join table has a composite key composed of the primary keys on the two related entities I want the hold the relationship for. The problem here is that I need to hold a relationship to the relationship so to speak.
This may be a problem with my database design or equally due to my lack of understanding with EF. It is probably best illustrated through example (see below);
I have three tables each with a primary key:-
Table : DispatchChannel
{ *DispatchChannelID integer }
Table : Format
{ *FormatID integer }
Table : EventType
{ *EventTypeID integer }
The relationship between EventTypes and DispatchChannels is held in EventTypeDispatchChannels (see below) since this only contains a composite key it is not pulled through into our model and entity framework takes care of maintaining the relationship.
Table : EventTypeDispatchChannels
{ EventTypeID integer, DispatchChannelID integer
}
My problem now arises because for each combination of EventTypeID and DispatchChannelID I want to hold a list of available formats, this would be easy if my EventTypeDispatchChannels table had a primary key therefore my other join table would look like this;
Table : EventTypeDispatchChannelFormats
{ EventTypeDispatchChannelID integer, FormatID integer
}
The absence of a primary key on EventTypeDispatchChannels is where I am struggling to make this work, however if I had the key then entity framework no longer sees this as a linked entity.
I'm relatively new to C# so apologies if I have not explained this so well, but any advice would be appreciated.
The moment you want to give an association a more important role than just being a piece of string between two classes, the association becomes a first-class citizen of your domain and it's justified to make it part of the class model. It's also inevitable, but that's secondary.
So you should map EventTypeDispatchChannels to a class. The table could have its own simple primary key besides the two foreign keys. A simle PK is probably easier, so your table Format can do with a simple foreign key to EventTypeDispatchChannels for the one-to-many association.
You will lose the many to many feature to simply address dispatchChannel.Events. In stead you have to do
db.DispatchChannels.Where(d => d.DispatchChannelID == 1)
.SelectMany(d => d.EventTypeDispatchChannels)
.Select(ed => ed.Event)
On the other hand you have gained the possibility to create an association by just creating an EventTypeDispatchChannel and setting its primitive foreign key values. Many-to-many associations with a transparent junction table can only be set by adding objects to a collection (add an Event to dispatchChannel.Events). This means that the collection must be loaded and you need an Event object, which is more expensive in database round trips.
Ì am currently working on a ASP NET MVC project. We use Entity Framework and follow the Database First approach. The database already exists.
The database has been created using the convention, that every table has a specified single primary key, even if it is a junction table.
Example :
Table User :
UserId (PK);
Username
Table UserRole :
UserRoleId (PK);
UserId (FK);
RoleId (FK)
Table Role :
RoleId (PK);
Rolename
As said, the database already exists and this convention is not discussable.
When I want to create an Entity Data Model in Visual Studio, I also have three Entities. But it would only make sense to have two Entities: User and Role. The UserRole Entity makes no sense.
Is there any possibility I can influence the way that Entity Framework maps my tables, so I can get rid of those relational (useless) entities?
Is there any possibility I can influence the way that Entity Framework
maps my tables, so I can get rid of those relational (useless)
entities?
No, you cannot force EF designer to do that. When using automatic tools you will always end with junction table mapped as a separate entity because it is not considered as junction table any more - it has special data (a separate key) which gives this entity new possibilities (for example relation between two entities can exist multiple times which is not possible with normal junction table).
The only way to avoid this is abandon tooling support and use either code mapping or manually write EDMX file and don't tell EF about that additional key. Instead let EF believe that there are only those two FKs forming composite PK as expected from junction table. Obviously if your database requires those special possibilities allowed by separate PK you cannot do this.
I've got the following entities on my EDMX :-
These two entites were generated by Update Model From Database.
Now, notice how my country has the following primary key :-
Name & IsoCode
this is because each country is UNIQUE in the system by Name and IsoCode.
Now, with my States ... it's similar. Primary Key is :-
Name & CountryId
Each state is unique by name and per country.
Now, the Foreign Key for States is a CountryId. This is the sql :-
ALTER TABLE [dbo].[States] WITH CHECK ADD
CONSTRAINT [FK_States_Countries] FOREIGN KEY([CountryId])
REFERENCES [dbo].[Countries] ([CountryId])
ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[States] CHECK CONSTRAINT [FK_States_Countries]
GO
Pretty simple stuff.
BUT EntityFramework doesn't like it :( It's assuming that i need to connect some properties from State entity to both primary key properties in the Country entity.
Is it possible to add an ASSOCIATION between Country and State on Country.CountryId <-> State.CountryId ... like i have mapped in my DB ?
Cheers ;)
In EF (3.5 and 4.0) FKs MUST point to Primary Keys.
But you appear to be attempting to point to a Candidate Key (i.e. [Countries].[CountryId]
I know that this is something the EF team are considering for the next version though :)
Hope this helps
Alex
For proper DB normalization, first thing is that primary keys must be only CountryId and StateId fields - the main Id fields for each table.
And ss I see from the description Name & IsoCode and Name & CountryId should be actually Unique keys, not primary.
Then the model class State should have a field:
public Country Country { get; set; }
Now EF have very good examples and since 4.3.1 + it fully supports Code first / DB first models, which I think will ease solving this.
EF 5 have more compatibility updates so I think it wont be a problem for legacy DB engines.
I have a Database model like this
FlowObject
FlowObjectID (PK)
Description
Active
ProcessObject
FlowObjectID (PK, FK)
HasSubmit
DecisionObject
FlowObjectID (PK, FK)
YesFlowObjectID (FK)
NoFlowObjectID (FK)
YesCaption
NoCaption
When I try and use create my Entity model I get this warning in my project.
Foreign Key constraint 'FK_ProcessObject_FlowObject1' has been omitted from the storage model. Column 'FlowObjectID' of table 'Investigations.Store.ProcessObject' is a Foreign Key participating in multiple relationships. A one-to-one Entity Model will not validate since data inconsistency is possible.
???
Why did it drop my foreign key? Because "A one-to-one Entity Model will not validate since data inconsistency is possible."
So it sounds like it is saying it dropped the FK because of data inconsistency but dropping the FK actually reduces date consistency?
Should I redesign my database? Is there anyway for L2E to handle FK's that participate in multiple relationships? Is it considered bad database design to have FK's that participate in multiple relationships?
What you've described, translated to object-oriented terms, is that a FlowObject contains an optional ProcessObject and an optional DecisionObject. If this is what you actually meant, the database schema is correct.
If you're trying to have ProcessObject and DecisionObject extend FlowObject, inconsistency is possible because both the ProcessObject and DecisionObject rows may exist. To eliminate the inconsistency, the union-subclass modeling technique is appropriate: only ProcessObject and DecisionObject tables exist, each containing all relevant fields, and FlowObject, as an abstract base class, becomes a view consisting of the union of the common base fields between the two tables.
I have just get the same error when trying to refactor this. In EFv1 (.NET 3.5) this cannot be solved. In EFv4 (.NET 4.0) you can change independent association (the only association/relation available in EFv1) to foreign key association and it will work. But FK associations have some other drawbacks so it is not a silver bullet.