I've two tables named Modules and Privileges which are related by a foreign key relationship as shown below:
(source: baburajpb at sites.google.com)
I'd like to model Module and Privilege by adding ModuleName to Privilege. Later I'd be interested in creating a derived class (Menu in the illustration) from Privilege by adding a discriminating condition on ModuleName. Is this possible using Entity Framework?
Can you map multiple tables to a single entity type? Sure, that is supported. However, you cannot use a mapped field of the table (ModuleName) as a discriminator column for table per hierarchy mapping. The discriminator column must be used as a discriminator alone, and must not be mapped into your client schema.
Related
I am extracting data from a set of JSON files into an MS T-SQL database using Entity Framework.
There are a bunch of sub-collections in the JSON files (counted 20 so far) that all follow the pattern "CollectionName":{"Code":"SomeCode","Description":"Some Description"}.
For example: "Country":{"Code":"GB","Description":"Great Britain"} or "Language":{"Code":"FR","Description":"French"}
The code I am working with uses this pattern: an Entity is created called CollectionName, which maps to a table with PK, Code & Description columns and then another Entity called SourceCollection (ex: PersonLanguage) which maps to a Bridge Table having the Source PK & CollectionName PK for each. When you have a lot of these little sub-collections, that is a lot of tables.
As a T-SQL programmer, I have solved similar problems in the past by creating a 'catchall table' that has a PK, a CollectionName Column, and then a Code & Description column as above. So all these little collections reside in a single table, with a foreign key pointer in the source table.
I cannot find any description of how to implement this in Entity Framework, can anyone point me in the right direction with either a link or some sample code?
The pattern you're describing is sometimes called a "common lookup table" and is generally considered an anti-pattern for reasons of referentially integrity and constraints.
Merits of the design decision aside, you have two options:
A) Create a new EF entity with properties for Id, CollectionName, Code and Description and map your existing classes and data to that entity for CRUD operations via some pattern such as Repository.
B) Use EF type inheritance with table-per-hierarchy mapping and allow EF to map multiple entities to the same table. The abstract parent type would have Id, Code and Description properties. EF will automatically create a discriminator column that serves the same purpose as CollectionName.
We have a database in which one table contains records that can be child to several other tables. It has a "soft" foreign key consisting of the owner's Id and a table name. This (anti) pattern is know as "polymorphic associations". We know it's not the best database design ever and we will change it in due time, but not in the near future. Let me show a simplified example:
Both Event, Person, and Product have records in Comment. As you see, there are no hard FK constraints.
In Entity Framework it is possible to support this model by sublassing Comment into EventComment etc. and let Event have an EventComments collection, etc.:
The subclasses and the associations are added manually after generating the basic model from the database. OwnerCode is the discriminator in this TPH model. Please note that Event, Person, and Product are completely different entities. It does not make sense to have a common base class for them.
This is database-first. Our real-life model works like this, no problem.
OK. Now we want to move to code-first. So I started out reverse-engineering the database into a code first model (EF Power Tools) and went on creating the subclasses and mapping the associations and inheritance. Tried to connect to the model in Linqpad. That's when the trouble started.
When trying to execute a query with this model it throws an InvalidOperationExeception
The foreign key component 'OwnerId' is not a declared property on type 'EventComment'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.
This happens when I have bidirectional associations and OwnerId is mapped as a property in Comment. The mapping in my EventMap class (EntityTypeConfiguration<Event>) looks like this:
this.HasMany(x => x.Comments).WithRequired(c => c.Event)
.HasForeignKey(c => c.OwnerId);
So I tried to map the association without OwnerId in the model:
this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
This throws a MetaDataException
Schema specified is not valid. Errors:
(10,6) : error 0019: Each property name in a type must be unique. Property name 'OwnerId' was already defined.
(11,6) : error 0019: Each property name in a type must be unique. Property name 'OwnerId' was already defined.
If I remove two of the three entity-comment associations it is OK, but of course that's not a cure.
Some further details:
It is possible to create a working DbContext model ("code second") from the edmx by adding a DbContext generator item. (this would be a work-around for the time being).
When I export the working code-first model (with one association) to edmx (EdmxWriter) the association appears to be in the storage model, whereas in the original edmx they are part of the conceptual model.
So, how can I create this model code-first? I think the key is how to instruct code-first to map the associations in the conceptual model, not the storage model.
I personally stick with Database first when using EF on any schema that is this level of complexity. I have had issues with complex schemas in regards to code first. Maybe the newer versions are a little better, but worrying how to try and code complex relationships seems less straight forward then allowing the engine to generate it for you. Also when a relationship gets this complex I tend to avoid trying to generate it with EF and try and use stored procedures for easier troubleshooting of performance bottlenecks that can arise.
I'm trying to port an existing application (using pure ADO.Net) to a new one using EF 4.3 Code First. It is worth mentioning that this is the first time I'm using EF.
Basically I have a suppliers table but with two specialization tables with attributes specific to each of the two types of suppliers.
Here is what the existing database looks like:
create table Supplier(
id_supplier int not null identity
--Bunch of other attributes
);
create table Individual(
id_individual int not null --not identity, gets the same value as the Supplier table
--Attributes specific to individuals
);
alter table Individual add constraint fk_individual_supplier
foreign key(id_individual) references Supplier(id_supplier);
create table Corporation(
id_corporation int not null --not identity, gets the same value as the Supplier table
--Attributes specific to corporations
);
alter table Corporation add constraint fk_corporation_supplier
foreign key(id_corporation) references Supplier(id_supplier);
So, as the tables show, a supplier can be either an individual or a corporation.
The existing application is like this:
abstract class Supplier with its attributes
class Individual deriving from Supplier with its additional attributes
class Corporation deriving from Supplier with its additional attributes
The Ado.Net code currently works receiving Supplier objects, generating records on Individual table if the object passed is of Individual type or Corporation table if the object passed is of Corporation type.
So, every record on Supplier will have a matching one on either Individual or Corporation. Also, Individual and Corporation tables does not have foreign keys to any other table of the database. Instead, the relations are all with the Supplier table. The table generating the ID is Supplier.
How can I map this with Code First?
At first I thought about keeping my structure, I mean, Supplier abstract class and Individual and Corporation deriving from that. Because I need Entity to insert on Supplier table first (generate identity field), it seems that both Individual and Corporation model classes would be mapped to Supplier table.
But how would it be possible for it to receive the abstract class and insert on either one of the specialization tables depending on the type? I don't think this is possible without custom SQL which makes me think my approach is wrong.
Thanks in advance for helping.
This sounds like "table per type" inheritance (TPT). With TPT there is a base table with columns that are common for all derived types and tables per derived types with type-specific columns. Entity framework supports this model. See this excellent blog post for examples how to do it both with data annotations and fluent mapping.
I am trying to come up with a database design that would work with Entity Framework 4 Code First. Actually, I have no experience yet of EF4 Code First but as I understand it, if I write the code, it will create the database and tables.
The issue is this. There are various types of auctions, they all have some common fields and some specific ones. In the code I envisage having a base abstract class called Auction and subclasses like LowestUniqueBidAuction and EnglishForwardAuction etc.
Nothing surprising there. The problem is that I imagine the database structure to mimic this. I imagine an Auction table and a LowestUniqueBidAuction table and a EnglishForwardAuction table. In the Auction table I imagine a foreign key into one of these two tables for each row depending on the type of auction that that row is. I also imagine another column in the Auction table with the name of the derived auction table (such as EnglishForwardAuction).
The problem is that whenever I've ever created a foreign key I've had to specify the name of the foreign table into which the key points (which makes sense). In this case, however, there is one of many tables that the key could point. So there are many issues here. Firstly, I could simply not use a foreign key and just use an ordinary field, but then the database will not be able to maintain data consistency for me. The second issue is how will EF Code First handle this? In other words, how will it know that if I ask for all EnglishForwardAuction rows from the Auction table that it should look at the column with the table name and then join on the EnglishForwardAuction table to get the extra fields?
Has anyone ever faced similar issues?
Thanks,
Sachin
This problem is solvable in Entity Framework in a number of ways - read up on how EF handles inheritance and what strategies are available.
There are basically three strategies how to handle this:
(1) Table per Hierarchy
You have only one single table, that represents all possible sub classes. Of course, this means, several rows (that only exist in a given subclass) must be nullable, since they don't show up / don't exist in super classes or other subclasses.
(2) Table per Type
Each subclass gets its own table, and by default, the sub-types table shares the PK with the base classes' table - e.g. PK = 1 in Auction will also be PK = 1 in EnglishForwardAuction. So your subclass tables reference the base table - not the other way around.
(3) Table per Concrete Type
Each concrete subclass (your separate auction types) gets its own table, but that table contains everything - all the columns, from that specific type, but also its base type.
Read more here:
Inheritance in the Entity Framework
Inheritance and Associations with Entity Framework Part 1
Entity Framework Modeling: Table Per Hierarchy Inheritance
Entity Framework Modeling: Table Per Type Inheritance
Searching for Entity Framework Inheritance and/or one of these strategies will reveal a lot more hits, too - that topic is very well covered and discussed on the interwebs! :-)
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?