NHibernate mapping class properties to Rows not Columns - c#

Is it possible to map a class with each property stored as a row in the table, not a column. The scenario is where we persist global options to the database. We store the options in an 'Options' class that has a property per option, i.e. "Expand Menu", "Save on Exit" etc.
Rather than store each option in its own table column, we would simply like to have a table with each of the class properties stored as a new row, identified by a Enum.
Is this possible?
(C# Winforms)

Using NHibernate's EntityMode.Map might help solve this problem. It does mean that you might have to put your global options in a Dictionary collection, but you can always implement an Option class that abstracts the underlying Dictionary.
NHibernate provides the ability to map a Dictionary dynamically to a table. See NHibernate's reference on Dynamic Models

Related

Best Practice with classes and the database

I would like to learn more about the appropriate way to use classes when using a database. Here is the example of what I think is ok.(Using C# and SQL Server if curious)
I Have a table called "Features" and most of the columns in it hold IDs(Foreign keys). To load that table into the application, I create a "DBFeatures" class to hold all the columns. Next I should have a regular "Features" class that has the actual values of all properties in "DBFeatures" class. "Features" class would have a method that opens a connection to the database to grab all the right values with the given IDs. Then The "Features" class can be used as is.
The same would go in reverse, I create an object of "Features", then it converts it into a "DBFeatures" class which gets passed to the database when INSERTING.
Is this the right way to go about this? What other options would be better? The only other option is just have one class, "DBFeature" class, and when I create an object of that class, each time a property is set or gets, it would have to access the database to get the value by providing an ID.
EDIT
I'll be using the data for forms. Most of the tables will be read only which will be stored into a list of objects which can then be used with Controls(like the data source of a combobox). Also I want to be able to load user input into a class that would be outputed to a table in the database.
A lot of planning on how to do something depends on your implementation which you are not providing. What are you planning to do with your objects? Is it for a report? Do you need to manipulate the values?
I'm going to assume you are going to be manipulating the data in which case you should have a class that opens the database and loads it into classes that represent it.
The class can have properties that correspond to the columns and then you can have a list of the class to represent the rows.
This is just one example of how to do it but its impossible to say without knowing what your intent is and having more details.
It looks like you need ORM like Entity Framework.

Code First Entity that doesn't include some required columns?

I'm trying to use EF6 Code First to map Domain Entities to a legacy SQL database. I do not have access to modify the schema of the database or create stored procedures. The table I'm trying to map contains a few required columns that I don't want cluttering up my Domain Entities, since they aren't relevant to my program (but they're used by other programs).
The problem is that my program also needs to be able to add new rows to this table. I have a set of values I'm supposed to use for these extra columns when my program creates a new row (these values aren't database defaults but are specific for new rows coming from my program). I've been trying to use a EntityTypeConfiguration to map all the columns, but I can't find a way to set default creation values for unmapped columns.
Is there any way to make EF6 aware of these unmapped columns and set specific default values on INSERT (but not alter existing values on UPDATE)?
You have to map this columns in your model, you can't create default values if you don't map these properties. What you can do is set this properties as private in your model and the map with Entity framework as is described in this blog http://romiller.com/2013/01/23/ef6-code-first-mapping-all-private-properties-using-custom-conventions/ using reflection.

XAF/XPO How to integrate legacy database

We are experimenting with DevExpress XAF & XPO in order to use it for our further devlopment of an existing small business ERP system. We have a SQL database, where the existing tables must not be changed. What we are trying to do is to add new needed table properties only to a new tables that then should be "connected" to the old tables through object inheritance (MapInheritanceType.OwnTable).
For example:
We have a legacy tCustomer table. Now we add an XPO object tCustomerExtended like
public class tCustomerExtended : test.Module.BusinessObjects.db.tCustomer ...
The tCustomerExtended class then shall be extended with new properties and the tCustomer class remains unchanged (in order to be used by the old client application).
This works fine of course. A new table tCustomerExtended is generated with a primary key kCustomer (the key of the legacy table). Also XAF generates a UI as expected: The tCustomerExtended view is empty, since it shows the tCustomerExtended entries.
!!! But what we really want to achieve is to show all existing tCustomer entries in this view and the new properties of tCustomerExtended. The OnSaving method should then save the legacy properties to tCustomer and the new properties to tCustomerExtended. Also we have to generate a kCustomer key, since the old tCustomer table kCustomer PK has no Identity Specification.
At this moment I do not realize how to achieve this without changing the old tCustomer (what is absolutely not allowed).
By default, when you create the subclass tCustomerExtended, XAF should generate detail views which include all the tCustomer properties too. I'm not sure why you are not seeing that behaviour.
Can't just add new columns to your old tCustomer table. So long as you don't change any existing columns, your old system should continue to work. Does your old system break if there are extra columns in the tCustomer table? If only minimal changes are allowed, you can just create an [Aggregated] property with [ExpandObjectMembers]. This will add a single column to the old tCustomers table which will provide the link to all the extended properties.
If you really do need two tables with zero changes to tCustomer, then I think you will need to jump through some hoops to achieve exactly what you want. It's certainly possible, but the best answer will come from the the DevExpress support center (as for all DevExpress-related questions). If you post a sample project there, the DevExpress team will quickly provide you with the best approach for your situation.

Oracle View base on a PIVOT query not null values

When creating a View based on a PIVOT query all the view fields become NULLABLE in the view metadata, is there any way to make them NOT NULLABLE?
I'm using the NVL function in the pivoted fields I need to be NOT NULL but they still become NULLABLE.
This is a problem to me because I'm using MS Entity Framework and it won't update the model based on tables or views without NOT NULLABLE columns.
#Miguel, I don't know the "MS Entity Framework" but the name makes it sound like a framework that is oriented towards editing data. 'Entity' is typically used for structuring a cache of database data in preparation for changing and updating that data back into the database. This does not seem like what you want to do.
Re-reading this question I believe that you have some sort of pivot generator you are using to create the view on-the-fly for the user. For this reason you do not intend to revise the Entity Model. I don't think you need an entity model at all.
An Entity Framework is likely to be looking for NOT NULL columns in order to find a 'primary key' or other row-level identifier that it can use. Why does it want these?
provide a key usable to update any row
provide key for paginating the result set
provide a key to support in-memory filtering of the result set
support dynamic sorting operations on the result set
I also surmise you have some sort of UI control that presents 'Entity' collections very nicely and so you want to use that control.
The control may not need an 'Entity' - check to see what its interface is. Perhaps there is a superclass of Entity or an interface that you can generate rather than an updateable Entity. If you can do that, you should be able to present it in the spiffy UI control and not hit the wall with your NULLABLE columns.
One of possible solutions is generating a new table on the fly based on results of query and tuning constraints for this table after that.
I don't like this method for too many dynamic SQL :)
Another solution is a prebuilt materialized view.
Look here (Oracle docs) for "ON PREBUILT TABLE Clause".
You need to update your model in Visual Studio (VS). Because this doesn't know what type information is in every column. Then you have to specify in the query of pivot table the data type. For example, Use to_number for specify a explicit conversion. When you going to update the model in VS you must based in for example materialized view (with explicitly defined data types). Please create Materialized view with explicitly defined data types based in the pivot table (this have to contain not only nvl function else defined data types, string, number, etc ) and then Update your model.
Only Materialized view? No, it can be a table (but is troublesome). Can be It direct of the pivot table? Does not always work (as in your case). Important Is to have defined data types.
You could use code-first if you don't have to many of these views, Scott Gu has a good article "Code first with existing database" that shows how to do this.
This might entail having 2 ways to access the db, which may or may not work for you.

Entity Framework Design - Multiple "Views" for the data

I have a design question related to Entity Framework entities.
I have created the following entity:
public class SomeEntity {
// full review details here
}
This entity has as an example 30 columns. When I need to create a new entity this works great. I have all of the required fields in order to insert into the database.
I have a few places in my app where I need to display some tabular data with some of the fields from SomeEntity, but I don't need all 30 columns, maybe only 2 or 3 columns.
Do I create an entirely new entity that has only the fields I need (which maps to the same table as SomeEntity, but only retrieves the column I want?)
Or does it make more sense to create a domain class (like PartialEntity) and write a query like this:
var partialObjects = from e in db.SomeEntities
select new PartialEntity { Column1 = e.Column1, Column2 = e.Column2 };
I am not sure what the appropriate way to do this type of thing. Is it a bad idea to have two entities that map to the same table/columns? I would never actually need the ability to create a PartialEntity and save it to the database, because it wouldn't have all of the fields that are required.
Your first approach is not possible. EF doesn't support multiple entities mapped to the same table (except some special cases like TPH inheritance or table splitting).
The second case is common scenario. You will create view model for your UI and either project your entity to view model directly in query (it will pass from DB only columns you project) or you will query whole entity and make conversion to view model in your application code (for example by AutoMapper as #Fernando mentioned).
If you are using EDMX file for mapping (I guess you don't because you mentioned ef-code-first) you can use third approach which takes part from both mentioned approaches. That approach defines QueryView - it is EF based view on the mapped entity which behaves as a new read only entity. Generally it is reusable projection stored directly in mapping.
What you proposed as a first solution is the "View model paradigm", where you create a class for the sole purpose of being the model of a view to retrieve data and then map it to the model class. You can use AutoMapper to map the values. Here's an article on how to apply this.
You could create a generic property filter method that takes in an object instance, and you pass in a string array of column names, and this method would return a dynamic object with only the columns you want.
I think it would add unnecessary complexity to your model to add a second entity based on the same data structure. I honestly don't see the problem in having a single entity for updating\editing\viewing. If you insist on separating the access to SomeEntity, you could have a database view: i.e. SomeEntityView, and create a separate entity based on that.

Categories