Store behavior class with nHibernate - c#

I would like to know if there is a way how to store classes only with behavior to database with nHibernate.
What I mean. I have a solution where I have used decorator pattern, something like on class diagram
Here is the problem what Iam trying to solve. I have a class ClassWithStoredBehaviorInProperty and has a property DesiredBehavior of type IBehavior. Somewhere else I mix up behavior f.e. var beh = new FlyBehavior(new WalkBehavior(new BatmanBehavior)) and store it in DesiredBehavior property. And here is my question. Is there any way how to store this in database with nHibernate and then Load it correctly or I have to do some workaround. If it is possible, how to map it? Thanks

You can have hierarchical data structures handled by NHibernate. From a database perspective, The Decorator Pattern is simply a hierarchical structure where there is only one child node rather than a collection. There is some introductory information here.
So you can quite easily map subclasses of the same hierarchy using the 'table per class hierarchy' approach, where each Decorator becomes a row in the table and points to an Inner Decorator. In your table you use a discriminator column so when retrieving from the database, NHibernate knows what type of class it needs to instantiate. Obviously the 'code' that realises the particular behavior associated with each Decorator would not live in the database.

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.

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.

Approach mapping objects to database entities

I have to create an import from excelfiles to a database.
I've created a little system which mapps my excelfile to some kind of "excel entities". Some of these entites contain information for more than one database table and for other entites I need to calculate the id in the database etc. I am using the entityframework to map the database to objects.
Now my problem is, that I need a clean approach to map between my excelfile structure and my database structure.
Is there any pattern to solve this problem in a clean way? I don't want to check every attribute whether it has changed,... I just need to synchronize the database with my excelfile. But the excefile does not exactly look like my database schema.
Would be very nice if someone would know a pattern or an approach how to solve the problem.
Looks to me like you actually have two problems to solve: 1) Get the information out of the excel files into a nice schema; and 2)synchronize the database. Looks like you have #2 well under control if you're considering entity framework. To solve your #1 issue, you more than likely have to create a parser that can fill in the entities that are created in your #2 solution.
TL;DR: Separate the file parsing from the synchronizing. Get all your objects first, then update the database.
Edit:
You'll have to create a mapper next. Something that can link two objects by property names. Look at "Reflection", "Extension methods" and a more generic search for mappers. I would create something that would work like this:
object1.Map("Property1",object2,"Property2");
object1 would be your database entity, Property1 the name of the property you want to map to, object2 would be the excel entity and Property2 the name of the property to map from.
PS: If the extension method is done correctly, you can 'chain' the mapping: object1.Map("Property1", object2, "Property2").Map("Property3", object3, "Property4")
and so on. You can even select different objects to map to.

How to create a business model wrapper for a generic database approach?

I'm currently facing a performance problem with creating POCO objects from my database. I'm using Entity Framework 4 as OR-Mapper.
The whole application is a prototype for now.
Let's assume I want to have some business objects like classes 'Printer' or 'Scanner'. Both classes inherit from a BaseClass called Product.
The business classes exist.
I try to use a more generic database approach. I don't want to create tables for "Printer" nor "Scanner". I want to have 3 tables: One called Product, and the other Property and PropertyValue (which stores all assigned values to a specific Product).
In my business layer I do create a specific object like this:
public Printer GetPrinter(int IDProduct)
{
Printer item = new Printer();
// get the product object with EF
// get all PropertyValues
// (with Reflection) foreach property in item.GetType().GetProperties
// {
// property.SetValue("specific value")
// }
return item;
}
This is how the EF model looks like:
Works fine so far. For now I'm doing performance tests for retrieving multiple sets.
I've created a prototype and improved it several times to increase the performance. It is still far away from being usable.
I takes 919ms to create 300 objects who only contain 3 properties.
The reason for choosing such DB design is to have a generic database design. Adding new properties should only be done in the business model.
Am I just being too stupid to create a performant way of retrieving xx objects or is my approach totally wrong? As far as I understand OR-Mapper, they are basically doing the same?
I think you missed whole point of ORM. The reason why people are using ORM is to be able to persist buisness objects and easily retrieve business objects. You are using ORM to get just data for your business objects' factories. Factories are using reflection to build business object from materialized classes retrieved by ORM. This will always be very slow because:
Query compilation is slow (you can precompile it)
Object materialization is slow (you can't avoid it)
Reflection is slow (you can't avoid it)
IMO if you want to follwo this DB design to have generic tables absolutely independent on your business objects you don't need ORM or at least you don't need EF.
The reason for your performance problems is that generic approach is not follwed in your business model. So you must somewhere convert generic data to specific data = slow operation.
If you want to improve performance define set of shared properties and place them into Product. Then either use your current PropertyValue and Property for additional non shared properties or use simply ExtendedProperties table storing key value pairs. Your entities will be of type Product with inner type property, shared properties and collection of extended properties. That is generic approach.
Firstly, it's not clear to me what you have in the way of POCOs. Did you hand code these and your context or T4 generate them? There are some great articles here that benchmark performance with no POCO, T4 Generated POCOs/Context and hand coded POCOs/Context. As expected there is HUGE performance savings going with POCOs (more than a 15-fold boost in performance in his benchmark) going the POCO route over those generated by the Entity Framework. You don't say what DBMS...if MSSQL have you turned on the profiler and see what's being generated?

Fluent Nhibernate - Mapping two entities to same table

I'm trying to map two domain entities to the same table. We're doing a smart entity for our domain model, so we have the concept of an Editable Address and a readonly Address. I have both mapped using Classmaps, and everything seems to go fine until we try to export the schema using the SchemaExport class from NHibernate. It errors out saying the table already exists.
I assume it's something simple that I'm just not seeing.
Any ideas?
Thanks
Update
There are a couple of other things I didn't mention which I should have. I appreicate those that answered so far, but they don't work for us.
One is that we have a single address table, not include the columns in whatever entities have an address.
The other is that we can't use a common base class. For editable objects, we have a super class which adds validation behaviors to the subclasses. The readonly objects don't need this behavior though and should not have these behaviors.
I have considered an interface, but then I believe I end up in a situtation where you can cast a readonly object to this interface and then changes its values (since presumably NHibernate would use said interface to hydrate the object).
So if there's another way to acomplish this, or if mapping via an interface won't have the problem I described, please let me know. I'm still learning NHibernate.
Thanks again!
you can Exclude the readonly class from schemaexport:
public class ReadonlyAdressMap : ClassMap<ReadonlyAdress>
{
ReadonlyAdressMap()
{
Schemaaction.None();
[...]
}
}
Create one base abstract class entity which you will later extend to the Editable Address and the ReadOnly Address.

Categories

Resources