creating a database with dynamic fields - c#

I have database to be designed about people info
there will be some common details about people like name,age,address,contact etc...
but there are categories of people like government servants,business man,salaried , politicians etc...
so there will be some dynamic fields about the categories...
common details table can be made easily but the problem is with dynamic fields of categories like
government servants will have income, dept, since,etc...
I have created three tables :
Peoples Table: name, age, DOB, etc...
Category:rows for Government servants, salaried etc...
Attributes:
------------------------
ID|Category|Field|Value
-----------------------
1 |GS |dept |electricity
the above database design (what i am using now) is kind of
NopCommerce database deign with
Nop_Customer and Nop_CustomerAttribute table
so is this a good one or anything better than this could be done: (for this situation)
Two imp points to be considered:
1-users will add data for this so controls will have to be created accordingly
2- this database will be searched by others.
EDIT:
The fields for each Category will be fixed.
but the categories will be added over time not by users but by developers, so need it be less hectic and maintainable for developers

Make tables for each type of person. In those tables, only store what is applicable. If Phil Jones is a politician, then he would have an entry in the Person table that describes him as far as a person is concerned. He would also have a row in the Politicians table that would describe him as far as a politician is concerned. Make each of the child tables have a foreign key relationship with the person table's ID column.

You could opt to use an ORM tool such as NHibernate:
NHibernate is a mature, open source object-relational mapper for the
.NET framework. It's actively developed , fully featured and used in
thousands of successful projects.
You could then use OOP principals such as inheritance to have one super class covering the basics and then extend the class depending on what other extra features you need. This tutorial gives you an idea on how to do it.

You can use XML field so You can store unstructured data or use one of inheritance mappings
see here http://www.agiledata.org/essays/mappingObjects.html

Related

Entity Framework Code First with Dynamics Navision Tables

I have a project where I need to design a code first entity system with an existing database. These existing tables in the database are not just any tables, they were being created by Microsoft's ERP tool "Dynamics Navision". The Navision tool holds different company information and creates different tables per company. Let's assume there are 3 types of tables;
TableX
TableY
TableZ
And also there are 3 different companies;
CompanyA
CompanyB
CompanyC
The tool created 9 different tables from above combinations. It simply duplicates all of the tables and adds a prefix with the company name to the table names. At the end, our database looks like this;
CompanyA$TableX
CompanyA$TableY
CompanyA$TableZ
CompanyB$TableX
CompanyB$TableY
CompanyB$TableZ
CompanyC$TableX
CompanyC$TableY
CompanyC$TableZ
What Did I do so far?
So as you can see, there is an opportunity to simplify this architecture at the Entity Framework side. To achieve this, I created 3 entity classes for TableA, TableB, TableC and at the run time, I let the user to choose a company and according to the chosen company, I reflected my entity class with a custom TableAttribute where the table name prefixed with the company name. I am not going to give details on how I achieved it right now(but you can find implementation details on this article: LINK) but so far so good and I have applied all of the previous steps successfully and I managed to be dynamic on table names with the chosen company. However, there is another problem.
What is my question?
The problem is, even though I managed to create a system where I can change the entity class' table name attribute at the runtime and access to the target companies tables, there were no guarantee that duplicated tables with different company name prefixes are sharing %100 same inner field architecture. For example, CompanyA$TableX can have 5 fields while CompanyB$TableX has 6 fields where the first 5 fields are the same with CompanyA$TableX's fields but the last 1 field is extra. Let's also visualize it;
CompanyA$TableX's table fields;
ID
Name
Surname
Adress
PhoneNumber
CompanyB$TableX's table fields;
ID
Name
Surname
Adress
PhoneNumber
EMail
As you see, the Email field is the extra however the table names are the same(TableX), only the company differs and in my system, they share the same entity class and the company name determined at the run time as I mentioned before.
So, I want to know about how can I achieve to be dynamic on this. How I can have only one entity class but be dynamic in the fields of this class according to the chosen company. I want to know if it is possible technically and if it is, how to implement it. Thanks in advance.
What you are saying about Nav is not true. It is not possible to create the same table in Nav that will have different structure per company. Even the modern extension architecture will not give you that kind of result.

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 add fields from one-to-one connected entity to a Datagridview

I created a winform that contains a datagridview with all entities of one of my database-tables. I did this by creating a datasource and creating a datagridview from said datasource (according to this: https://msdn.microsoft.com/en-us/data/jj682076.aspx).
Now I have a nice datagridview and I have started customizing it. My problem is: I would like to get information from the connected entities. E.G. my table contains a list of books. Each book is connected to one author. Now I can simply overwrite the author-entities ToString-Function and have a column that specifies the author of each book. But how would I add another column that shows the DOB of the books author? I feel like, there is probably a way to edit the datasource to fit my needs but I have no idea how ...
Thanks :)
I think it is good to separate the display of your data from the way it is actually saved into a database. This way your display doesn't have to change if your database changes.
Suppose you are creating a school database with students and teachers, who are - contrary to popular belief - both Persons with name / address / telephone numbers, etc. Because relational database don't know the concept of inheritance you'll have to think of a method of where to put the inherited Person data: In a separate table? as part of the table with Teachers and as part of the table with Students? Or maybe another approach. Your choice depends on your expectations on how the data is used.
If during lifetime of your program your approach changes, you don't want to have to change all users of your data. Hence you hide how your database is organized internally.
You'll probably have organized your datagridview into rows of things that users experience as belonging together: with a book they want to see the author and his data of birth, and probably some other items. Humans are not interested that internally you have separated the author from his book.
Therefor the best way for you is to create a class that represents the user's idea of a row in your datagridview. So, an class with book, author and a date of birth properties. When the object of the class is created all items are filled from the database using the proper join and / or include statements.
Consider retrieving the data from the database only when asked for.

What's the best way to persist a dynamic "info" object, C#/.Net MVC/SQL Server 2008?

This may sound like a pipe dream, I'm wondering if it's possible. I want to be able to take a C# dynamic object, called info, and persist it to a database (I'm currently on a SQL Server 2008 database).
The info object, being dynamic, could have any number of properties: Id, Title, Content, DateExpires, DateAdded, Dateupdated, TypeOf, etc...
Each instance of it could/will contain differing number of properties, depending on what the instance is used for: blog post, classified ad, event, etc... However, there would be a core set of properties every info object would share: Id, MemberId, TypeOf...
The idea is, to have a central table which stores all dynamic info objects, yet, allow me to query based on any property (which may not exist for some objects).
For example, blog posts. They'd have: Id, MemberId, DateAdded, Title, Content, TypeOf, etc... An event would have: Id, MemberId, Title, Content, TypeOf, DateOf, Recurrance, MinAge, MaxAge, etc...
I'd like to build queries based on any given info object property.
Why? Flexibility. If I can get this working, I can use the info object for future cases within my web app. If this is an extremely bad idea, please let me know (and why) please. Thanks!
This is possible and I've seen many systems built like this...however those systems are usually the hardest to maintain due to this "generic nature". There is nothing inherently wrong with this approach. It's just that it's much harder to pull it off and in most instances it ends up being a poorly implemented.
In recent years non-relational databases (like document databases that #Marc Gravell mentioned) have caught up and they are very good for some domains but you need to make sure it's the right fit for your project.
When you take the path of building this "generic database" you are sacrificing other well-known technologies that we take for granted. For example database optimization in relational databases is well-known and there are many tools that work well with them with little or no effort. If you go a different path all of a sudden the tools that you are used to might not work and will end up either building your own to make up for the stuff that does not work (or buying/choosing some esoteric tools.)
Depending on the size of your project it might be wise to build one or two of those systems that you think would be common and then try to see if they are as common as you think.
you could use a 'base' table for the common properties, and a property name-value table for the other properties. meaning:
Table Info
int Id (PK) (FK),
int MemberId,
Date DateAdded //etc...
Table Properties
int InfoId (PK),
varchar PropertyName (PK),
varchar PropertyValue,
string PropertyType //optionaly store information about the type of property
after querying, you can use reflection to translate the properties from (name,value) pairs into proper properties.
That said, I think that this is a very bad idea, for several reasons:
1. this creates further complexity on your CRUD logic
2. you don't have well-defined entities in your domain model, which I don't like
3. validation is that much more difficult- you have to manually verify that Post, for example, doesn't have a property called Recurrance field.
I would use this method only if you truly need this flexibility- for example: if a user can choose to save custom properties that you don't know in advance.
otherwise, if you know that your entities are limited to Post, Event, Employee etc.., I would just limit myself to that.

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