EF many-to-many relationships from multiple different tables - c#

Let's say I have 4 tables: tbl_dogs, tbl_cats, tbl_birds and tbl_fish each with their own _Id columns, of course.. I want to create the ability to have many-to-many relationships between any of these tables. In my head, I picture a tbl_relationships table that has 2 columns: animal1_id and animal2_id and I can entries can be cat_12 | dog_3, bird_1 | dog_9, fish_8 | cat_4, etc. This is a 2 part question:
1) is this possible with EF code first? meaning the two columns on my "relationships" table can actually be pulled from multiple different tables? If so, how would I define that in the EF classes?
2) what if rather than animal1_id and animal2_id as the columns, I wanted to have parent_animal and child_animal so that when I went to look at a fish, I could pull all the child_animal records that have that fish as a parent_animal as well as all the parent_animal records that have that fish as a child_animal?
Any help would be greatly appreciated, thank you!

It's not possible with any relational database. Entity Framework is beside the point. A foreign key has to be made to a specific table. Period.
The Python framework, Django does sort of what you're looking for with its generic content types, but it's more of a hack than anything. For each generically related item, two columns are set: one for the type of the object and one for the id of the object. There are no foreign keys, because again, foreign keys are impossible in this scenario.
In the framework code, in order to materialize the related object, they then issue a query to the correct table (based on the object type) using the object id. However, this is much simpler in Python than C# because Python is duck-typed.
You can technically achieve the same thing, in C# if you were properly motivated, but it would be an entirely manually endeavor. Entity Framework is of no help to you here. You would also need to employ reflection in order to materialize the right type in the end, and reflection is both a pain in the posterior and hugely inefficient (slow).
That said, since the specific scenario here deals with things all of a certain type, animals, you can sort of achieve what you're looking for with inheritance. In other words, you can create an Animal entity and then have each of Dog, Cat, Bird, Fish, etc. inherit from Animal. Then, you can create a foreign key to Animal and interact with any of them. However, you would only be able to interact with them as Animals, not as specifically a Bird, for example.

If you need to have a single matrix table with just two columns, and you need each animal type to be in its own table, then Chris Pratt’s answer is succinct.
If you can go with more than two columns but are forced to stick with individual animal tables, I would try to have a column for every animal table in the matrix table and turn this matrix table into a massive multi-columned monster.
If you are limited to two columns in the matrix table but can target a matrix table based on what parent/child combo you are looking for, then I would set up twelve matrix tables and have each of them for one of the two possible animal combinations for each pair of animal tables. Obviously you are going to have issues if the number of animal tables is actually much larger.
If the animal tables will all have identical columns (type/content/requirements) themselves, there is a possible workaround. You can have all animals in one table with an identifier that signifies what kind of animal it is. This would typically be a foreign key attached to a lookup table of animal types. Then you can have your matrix table as both parent and child columns, as they will have explicit relationships to just a single other table (the ‘mass animal’ table; both parent and child would point to its PK).
A more elegant possible workaround to the prior paragraph (which I haven’t had a chance to use yet, so I am really hazy on its implementation with respects to gotchas) is Inheritance. Inheritance allows you to combine several tables that hold near-identical (in terms of fields and data types) collections of data, and be able to tell those collections apart by means of a discriminator. That way, as per the prior paragraph, you could have a single Animals table with a discriminator that indicates what each row is (cat, dog, etc.), and a matrix table where both the parent and child point to the ID of the Animals table. Since each column in the matrix table has an association to a unique table (instead of multiple tables), this could work out well.

Related

Dynamicaly changing the type of a parameter in an Expression without knowing the target type at code time

Lets say i have an Animal class which has some descendants that derive from it like Dog Cat and Mouse
public class Animal{}
public class Dog : Animal {}
public class Cat : Animal {}
public class Mouse: Animal {}
Now lets say entities of those objects are stored in sql database and that i use Entity Framework for communication with that database. Dogs, cats and mouses are all stored in different tables, but in code they share the same parent from which they derive.
If i want to get all animals that fulfill the same expression i would have to query each DbSet separately and give it the same expression but with different type of parameter, so a cat gets a cat parameter type and a dog gets a dog parameter like this
var cats = context.Cats.Where(p=>some expression);
var dogs= context.Dogs.Where(p=>some expression);
var mice= context.Mice.Where(p=>some expression);
var animals = new List<Animal>();
animals.AddRange(cats);
animals.AddRange(dogs);
animals.AddRange(mice);
But, this poses a problem to me, because if i ever wanted to add another animal type for example Bird i would have to add another line of code that gets the data from database and adds it to the result collection. This behaviour is badly managable and i would want for it to loop through types that derive from Animal and programaticaly construct an expression for proper type based on provided source expression which is passed as a parameter to method as a Animal type expression. Something like this:
public List<Animal> GetAnimals(Expression<Func<Animal, bool>> expression)
{
var animalTypes = GetTypesDerivingFrom(typeof(Animal));
List<Animal> animals = new List<Animal>();
foreach(var animalType in animalTypes)
{
var typeTranslatedExpression = GetTypeTranslatedExpression(expression); //i dont know how to do this part
var portionOfAnimals = context.Set(animalType).Where(typeTranslatedExpression).ToList();
animals.AddRange(portionOfAnimals);
}
return animals;
}
Is there any way to do this? I thought about changing the expression parameter type but i cant seem to figure it out without knowing the proper parameter type at code time.
I think you should have a look at your data design again. It is here you can solve a lot of your problems.
You can use a SQL SERVER VIEW to return your animals from different tables, using a UNION from the relevant tables. Adding a new animal table requires a new UNION in the view.
You can also perform the same using a stored procedure. I would use one for getting the animals and one for saving an animal to ensure the correct table is updated.
You can store all animals in one table and have an AnimalType field that links to another simple table with ID and AnimalTypeName. Adding new animals is then simple.
There is also Entity Framework inheritance with tables to consider
https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt
A can suggest you an easier solution. Since in code you do have Animal as a parent, you could do the same for the database.
More exactly, instead of having different tables for Cats, Dogs, etc., have one table Animal(since the properties should be the same), with a property something like "AnimalType", an enum.
And from here queries would be very simple.
It's not the best solution, but it's a viable one.
I like to leverage the power of the database application rather than assume that C# code (for retrieving data) is more efficient. I also see it as a separation of concerns. It is the case that one requires some skill in setting up database tables (key, other indexes and so on) as well as views, stored procedures, etc.
Inheritance of objects in a database is not an uncommon scenario. You can go several ways about it. Which is best depends not least on how much rows and columns are involved and what you want to do with the data. Using your animals hierarchy as an example:-
It is common in inheritance to push generalisation upwards and specialisation downwards, so we start by creating an "Animals" table. This has an integer field "Id" which is the key. We also have a field "Animal Name".
Now let's create a "Cat" table. And "Id" field is used but we have a foreign key "AnimalId" that links to the Animal table "Id". We add other fields common to cats. We do the same for mouse and other animals, pretty much as you have started.
Another way to achieve the above is to use one table for all animals. Now you need more columns for more animal types. This has a higher maintenance approach where changes might occur often, but works well where smaller, fixed ranges of objects are used. A simple way to retrieve some common data regardless of type is to use a computed column that outputs a varchar from the relevant fields for each object type.
Yet another way is to have a single animal table with all of the common properties. A second table stores Property Name/Value pairs. Each animal can now have any number of varying properties and it is simple to maintain from front-end code. This data structure has a simple, fixed design, yet still supports all you have requires so far. However, how useful this design is to you depends on how much analysis of the data is required. In the database you will have to flatten this row-based data into columns for some analysis processing.

NHibernate map join table with extra column

I have 3 tables: Workspace with PK IdWorkspace and other columns, Language with PK IdLanguage and other columns and join table WorkspaceFooter with multiple PK (IdWorkspace FK and IdLanguage FK) and extracolumn string Denomination. I cannot find a way to map those in Nhibernate, a way that WORKS.
How should I write in the .hbm.xml files? What should I map in Workspace? A collection, a list of WorkspaceFooter etc.?
Please keep in mind that for some reason the relationship in Workspace that points to WorkspaceFooter needs to be inverse="true". An update in Workspace must force an update in WorkspaceFooter too.
Thank you in advance.
You need to be clear about:
the class model you need (derived from the business logic, not just the database model)
Whether you really need a bidirectional relation
You could:
map it as an independent entity in a list (which is the solution with the most management code required),
map it as a composite element with the denomination and a many-to-one to the language. It also uses a specific class in C# for this. Probably the most straight forward solution.
map it as a map (dictionary in C#), where the denomination is the key (given that it is unique within the same workspace and a typical way access the language),
probably you can map it as a list and use filters to access only data of a certain denomination. I don't have experience with filters and I don't know what kind of troubles you may face.

How to persist inherited objects to database ? (about DB architecture)

I have a conceptual problem. It's about the correct Database architecture for persisting inherited objects. I'd like to have the proper way to do it, not using EF Code First, because this is all conceived beforehand, and is not necessarily used with EF, it may be, but not sure, or not only. I need a proper way which still will be consistant with ORM approaches, like Entity Framework.
Let's simplify and say we have an object called "Transportation Vehicle" : TransVehicle, it has following properties :
Name
Color
Age
Let's say now we have a "Car" inheriting from the TransVehicle, which adds following properties :
FuelType
WheelSize
We also have a "Plane" which adds those following other properties :
EngineQuantity
MaxTakeOffWeight
So, I may have in my code a List which will contain Cars and Planes.
I suppose I could have a table "TransVehicle" with fields like "Id, Name, Color, Age", then a table "Cars" with fields like "Id, FuelType, WheelSize", and a table "Planes" with fields "Id, EngineQuantity, MaxTakeOffWeight".
I could say :
I read "Plane" rows and complete with informations coming from "TransVehicle" with the same ID.
I read "TransVehicle" rows, and for each, see if I find a Planes record or a Cars record to instanciate the proper object.
I read "TransVehicle" rows, and look an enum value (string, int ?) in a special field to have the object type, then depending on this type, get the informations from the "Plane" or "Car" table.
Which is good conceptual practice ? Have you other tips ? Which way will be easy to map in an ORM ?
This is common problem of mapping an object hierarchy to relational model. You can read about it all over the web.
You basically have three options:
Hierarchy as single table - hierarchy is flattened into a table with discriminator column.
Table for each class - each class has its own table and you do join over all of them with complex queries to get the data. This is what you are doing.
Table for each concrete class - middle ground between the other two if you have abstract classes in the hierarchy
Most ORMs do allow you to pick which one fits the hierarchy best or even mix and match between them for maximum performance or storage savings.

Entity Framework 4 and SQL Server 2008 Multiple Possible Foreign Keys

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! :-)

How do you build extensible data model

I'm thinking of building a ecommerce application with an extensible data model using NHibernate and Fluent NHibernate. By having an extensible data model, I have the ability to define a Product entity, and allow a user in the application to extend it with new fields/properties with different data types including custom data types.
Example:
Product can have an addition fields like:
Size - int
Color - string
Price - decimal
Collection of ColoredImage - name, image (e.g. "Red", red.jpg (binary file))
An additional requirement is to be able to filter the products by these additional/extended fields. How should I implement this?
Thanks in advance.
I think this link describes kind of what you want...
http://ayende.com/Blog/archive/2009/04/11/nhibernate-mapping-ltdynamic-componentgt.aspx
More info on dynamic-component:
http://www.mattfreeman.co.uk/2009/01/nhibernate-mapping-with-dynamic-component/
http://bartreyserhove.blogspot.com/2008/02/dynamic-domain-mode-using-nhibernate.html
The idea behind dynamic-component is that you can build your data model by not having a one to one mapping of databse columns with properties. Instead you have only a dictionary property that can contain data from as many properties as you like. This way when you fetch the entity, the dictionary gets the data of all columns configured to belong in there. You can extend the database table's schema to include more columns and that will be reflected to the databse model if you update the mapping file accordingly (manually or though code at application start).
To be honest I do not know you can query such entity using the "attributes" property but if I had to guess I would do an IN statement to it.
One of the options is EAV model (Entity-Attribute-Value).
This model is good to apply if you have a single class in your domain, which table representation would result in a wide table (large number of columns, many null values)
It's originally designed for medical domain, where objects may have thousands of columns (sympthoms).
Basically you have
Entity (Id) (for example your Product table)
Attribute(Id, ColumnName)
Value(EntityId, AttributeId, value)
You can have some additional metadata tables.
Value should better be multiple tables, one for a type.
For example:
ShortStringValue(EntityId, AttributeId, Value nvarchar(50));
LongStringValue(EntityId, AttributeId, Value nvarchar(2048));
MemoValue(EntityId, AttributeId, Value nvarchar(max));
IntValue(EntityId, AttributeId, Value int);
or even a comple type:
ColorComponentsValue(EntityId, AttributeId, R int, G int, B int );
One of the things from my experience is that you should not have EAV for everything. Just have EAV for a single class, Product for example.
If you have to use extensibility for different base classes, let it be a separate set of EAV tables.
Onother thing is that you have to invent a smart materialization strategy for your objects.
Do not pivot these values to a wide row set, pivot just a small number of collumns for your query criteria needs, then return a narrow collection of Value rows for each of the selected objects. Otherwise pivoting would involve massive join.
There are some points to consider:
. Each value takes storage space for foreign keys
. For example row-level locking will behave different for such queries, which may result in performance degradation.
. May result in larger index sizes.
Actually in a shallow hellow world test my EAV solution outperformed it's static counterpart on a 20 column table in a query with 4 columns involved in criteria.
Possible option would be to store all extra fields in an XML structure and use XPath/XQuery to retrieve them from the database.
Each extensible entity in your application will have an XML field, like ExtendedData, which will contain all extra properties.
Another option is to use Non-relationnal Databases which are typically suited for this kind of things.
NOSQL databases(couchDB, mongoDB, cassandre...) let you define dynamically your propretyfields, you could add fields to your product class whenever you want.
I'm searching for similar thing and just found N2 CMS (http://n2cms.com) which implements domain extensibility in quite usable way. It also supports querying over extension fields which is important. The only downside I find out is that it's implemented using HQL so it would take some time to reimplement it to be able to query using QueryOver/Linq, but the main idea and mappings are there. Take a look on ContentItem, DetailCollection, ContentDetail classes, their mappings and QueryBuilder/DetailCriteria.

Categories

Resources