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

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.

Related

Orchard model inheritance with Table-Per-Concrete-Type?

I know that the underlying ORM used in Orchard is NHibernate and it does support the so-called ClassMapping which may help customize the mappings the way we want.
However I'm not sure about how Orchard utilizes the mapping methods supported by NHibernate. In this case it seems to always use the strategy similar to Table Per Type in EF as well as some other ORMs. With that strategy, the base class will be mapped to some common table whereas the derived class will be mapped to another table which contains all properties of its own (not declared in the base class). Those 2 tables will have a one-one relationship.
Now I really want to make it use the strategy similar to Table Per Concrete Type in which the base and derived classes will be mapped to 2 different tables with all properties (including inherited properties) being mapped to columns. Those 2 tables will not have any relationship, so querying for columns in just one table will not unexpectedly generate an inner JOIN (for one-one relationship).
Actually that requirement makes sense in case we just need to partition our data (from 1 big table to 2 or more small tables that have the same schema). We don't want to re-declare or use some kind of duplicate model classes (with different names), instead we just need to create a new model class and let it inherit from one base model class containing all necessary properties.
With the current code like this:
public class ARecord {
//properties ...
}
public class BRecord : ARecord {
//empty here
}
Currently we cannot use BRecord because it is understood as another part of the ARecord, the auto-generated query (always with INNER JOIN) will be failed because of some does-not-exist table or column names.
How can I solve this?
You're not going to like it ;) In a nutshell, the answer is don't do inheritance at all. Orchard was very deliberately designed around the idea of composition, steering well clear of inheritance in its content models. Maybe the central idea in Orchard is to make the concept of content part the "atom of content", and to design those basic units as very simple and composable pieces of functionality that do one thing well.
After all these years, the concept has held remarkably well, and I've yet to see an example of a content model where inheritance would have been more elegant and appropriate. This is reflected in the way nHibernate is customized and used in Orchard, as you've discovered.
So the solution to your problem can likely be one of two things:
You're modeling contents, and you should re-think your approach towards composition of parts. If you give a little more details about your specific scenario (maybe in a new question), I'm happy to help specifically in this direction.
You're modeling non-content data, in which case you might want to consider opting out of Orchard's specific nHibernate content-specialized idiosyncrasies and do things closer to the metal. Again, if you give more specifics about your scenario, I'm happy to take a look and give some pointers.

EF many-to-many relationships from multiple different tables

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.

Making generic getters and setters

I have a problem where I have to get the column names and their values from all the Tables in my schema and show that the result in a grid.
I have used the direct approach for this but I have to implement the SqlSiphon structure. For this I have to make getters and setters of each of the column of each Table in the schema which is impossible.
What should I use to get the Column names and their values dynamically from the table.
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = '" + #Tablename1 + "' AND TABLE_SCHEMA='dbo'"
What will be the best dynamic solution?
And what will be Best to use List , Dictionay or something like 2d Array which will give the column names as well as column values?
A few suggestions:
I'm not completely clear on what you're trying to achieve, but consider using an ORM (Linq2SQL, WEF, NHibernate)
In .NET, a suitable type to represent a database table would be a DataTable
Edit: After a few more re-reads I think I understand what you're asking - you already have a database/schema and you want to automatically create the entity classes needed by SqlSiphon. This is called "database-first" (as opposed to model-first). However, from a brief scan of the SqlSiphon documentation it appears it does not support database-first. Is this why you are trying to put the columns into a grid - to make it easier to manually create the entity classes for SqlSiphon?
Edit2: Note that trying to use an ORM on top of a database whose schema is frequently modified will be problematic. My next guess is that you're trying to figure out how to create an entity class in SqlSiphon which you can use to retrieve database schema information like table columns? I'm still struggling to understand what you're actually asking here - perhaps you can update your question?
Edit3: I think the answer to your question is take a different approach to your design - ORM's like SqlSiphon are not intended to be used to retrieve and modify the database schema itself.
Might be worth taking a step back an comparing against how other people solve similar problems.
Typically, each table on a database represents an entity, and you also have a class per entity, and you may use an ORM system to avoid duplication of work. So, in a typical system, you have a table for customers, and a table for invoices, and a table for invoice lines, etc. and then a class that represents a customer, a class for an invoice, a class for an invoice line, etc. As you later add functionality (and possible columns/properties) you change the classes, rather than just seeing what columns are on the database - you can of course decorate these with XML documentation and get Intelisense goodness.
There are many ORM systems out there, and each have their strengths and weaknesses, but I personally like LINQ to SQL for adding onto an existing data model.

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