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.
Related
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.
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.
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.
I think this is a question of the best technique or best way to skin a cat!
Imagine a menu with items (menu choices) on it. I have a table called MenuItem, which for example "Spaghetti Bolognese", it has lots of other information associated with it aside from just a better description and picture.
Eg.
Basic Information (Name, Description, Picture, etc)
Nutritional Information (approx 15 columns)
Allergy Information (approx 16 columns)
Dietary Information (another 7 columns) (religious etc)
As it is at the moment I have it all in the one table in SQL server, which is logical database design to me as it doesn't repeat, despite it making the field list for the table longer than I would like. I'd already been feeling a bit bad about just continually extending the database table. But now we also want to add 'Recipe' information, approx another 7 columns.
I'm using Entity Framework 4.latest, and feel there is probably functionality to help me split this off within the EDMX? (Is that what ComplexTypes are?) Or do I just need to do this in the ViewModel class I call?
I think what I'm after using in my code to segregate things better is something like
MenuItem.Recipe.Ingredients
MenuItem.Nutrition.Fat
etc
Complex types can help you but be aware that complex types cannot contain navigation properties, cannot be null and are always loaded with the entity. Other possibility is to use table splitting - this will allow you to map multiple one-to-one related entities to the same table. The main features of table splitting are:
Entities can share only primary key properties
There is one main entity and others are considered as relations (navigation properties)
Related entities must exists - they are not optional so when you insert new main entity you must insert these related entities as well even if they are empty
Related entities must be loaded with eager, lazy or explicit loading
I have a table that, some of its columns are unknown at compile time. Such columns could either be of an integer value, or some Enum value. There is a table that holds all the names of such dynamic columns and also holds the column's type. This "metatable" has the following columns:
DynamicColumnId (Pk)
Name
TypeId (Integer / Enum, as Fk from a separate table)
Integer columns have the Name from this table, whereas Enum columns are Fk columns from a table that has that Name, with some modification (e.g. a "DynamicTable" prefix).
The only solution I could think of for this situation is using Reflection.Emit to dynamically create an Entity class and a corresponding Mapping class. Admittedly, I'm new to NHybernate / Fluent NHybernate and it seems like a relatively simple hierarchy between the tables, and so I wanted to verify my solution isn't as ugly as it initially appears...
I would also welcome solutions that completely disregard my table hierarchy, in order to effectively acheive the same results (that is, to enumerate the rows on the dynamic table, going over all the columns, with knowledge of whether they are Enums and, if they are, their possible values as well).
(Edit: Additional information re problem domain)
I initially included minimal details, as to avoid Too-Much-Info related confusion.
This description is much more complex, but it unravels the motives behind this design.
The application involved is designed to automate log/dump analysis. Analysis-scenarios are frequently provided by the log/dump experts and so, in order to streamline the typical process of requirements=>implementation=>verification cycle, such analysis-scenarios are implemented by the experts directly as an Iron Python code snippet, with some domain-specific constructs injected into the snippets' scope. Each snippet has a "context" for which it is relevant. An example of "context" could be "product," "version," etc... So, the snippet itself is only invoked in certain contexts - this helps simplifying the Python code by eliminating branching (you could view it as Aspect Oriented Programming, to some extent). A non-expert could use the application, with a given code-context database, to analyze a log/dump, after choosing values for the various contexts.
When an expert decides that a new context is required for cataloging a certain code snippet, he could add a context, indicating the possible values it could have. Once a new context is added to the database, a non-expert that runs an analysis will be given the option to choose a value for the newly-added context.
The "dynamic table" is the table that associates a code snippet with values of the various contexts (columns) that existed when the snippet was issued, plus default values for the columns that did not exist at that time.
I won't claim to fully understand your scenario, but it seems to me that you'd be better off using a key-value store such as Redis or a schema-less database like CouchDB instead of SQL. This doesn't seem to be a problem for a relational database, but if you really need to use a RDBMS I'd map NHibernate as closely as possible to the real schema (DynamicColumnId, Name, TypeId) then build whatever data structure you need on top of that.