I am creating a database system where there are tables that have some data that are not user derived, they will be used by the app for lookup mainly. But for the database performance and query optimization I decided to use enums for these lookups and store their ints in the table instead of the entire word.
I want to make an enum called diseases and they are 500 types.
So, can I create an enum in C# (.net core) that has 500 members and, if not, how can I achieve such thing? Also, is there a way to localize the values in enums?
I use the enums because they will save me the joining when I make queries in database. If I didn't use enums I would have to query a table then make 2 joins with another 2 tables that have the lookup data. If I make them with enums though, I only need the number which will be saved in the first table and in the app get its string and I will save the query from using 2 joins every time I get the data.
Can I create an enum in C# (.net) that has 500 members
Sure, if you want to.
But I think it's a bad idea. Imagine if someone else wants to use your Database, they'll then have to have a copy of the same enum, which means you'll have to maintain 2 (or more) copies of the same list as long as other people need it and I don't think anyone wants to do that.
500 rows in a Database is like nothing, making it into an enum won't help you that much (at least not something you can notice), instead just store them in a Table and everyone is happy.
Is there a way to localize the values in enums
No, not out-of-the-box. You will have to create your own solution for this. It depends on where and how your localizations are stored.
Related
Say if I have a column in database which can accept any one value of the enum that is defined in my C# code.
There is a usual way to make it be available to the database to store it in a database table and refer it from there.
But sometimes you don't want to store the enum in the database but just want to maintain it in the code, for these cases I have come up with the solution in my project to have a view which will return the values of enums so that we do not have to hard code it in the database, so having something like this in the database
CREATE VIEW ENUM.ValidationFailReasonTypes
AS
SELECT 1 AS [FormLevel], 2 AS [GridLevel]
For enum
public enum ValidationFailReasonTypes
{
FormLevel = 1,
GridLevel = 2
}
So just wanted to ask is it a good idea to do like this or is there some better way to handle this case when we don't want to store enum in the database?
It all depends.
Old school database folk like me want you to build validity checks into your data model. See this question for how you would do that. You end up with a nice, self-documenting schema, which guarantees that your application can only contain valid entries for ValidationFailReasonTypes.
An alternative view is that the database is just the storage mechanism, and it's perfectly OK for the application to be the guarantor of data validity, especially if it has lots of unit tests. In this case, you use an ENUM in you C#, write unit tests to validate that the entries match your expectations, and accept the fact your database table has an integer column which could contain lots of values, but the application limits it to (1, 2).
I think it's important to pick one approach and stick to it. Your solution - if I understand it correctly - is a bit of both.
In general, I'd use an enum for values that are not going to change without a new release of your application, usually because you're enabling some new functionality.
I'd expect to use a database entry for something that can change in the business domain independently of your application's release. "Grid level" and "form level" feel like features in your application, so I think an enum is okay.
The entire reason for an enum is consistency, clarity, and ease of use when coding. I would think you would want that sort of clarity and consistency on the database side as well. If you persist an enum value to the database, you absolutely should have referential integrity on the column and a corresponding definition table. The view saves you nothing in my opinion.
Create a table and add referential integrity to the field even if it only has two rows for all eternity.
I'm developping an application and I often ask myself the same question.
For example, I have many types of user and in a form used to create a user, there is a dropdown to specify which type of user.
The best way to populate this dropdown is to store values in a database's table ? If I do this, when I develop I want to test type of user and I have only an int. But I thing it's a better practice to test with enum. So I create enum but I feel it's a bad practice because I have to keep database and enum synchronized.
Another question is about localization. If I put values in database, I can't use resource file.
Could you tell me good pratices about this ?
Thanks
in your situation - the database would be the best practice here especially if its dynamic data. enum is for those values which are rarely to change, maybe once in a while but not on a frequent basis. you may have new entries entered in the database regularly especially for things like cascading drop down lists.
database certainly is the way to go in your situation. Enums are there for those times where they are just a set standard and rarely to change, for example:
Mr.
Miss.
Mrs.
Ms.
Dr.
you would have these in enums as they will never really change. on the other hands if store departments are to be changed or renamed, database would be the place to store such entries.
I strongly disagree with using enums for this kind of functionality, for basically two reasons:
Enumeration values have no behaviour, so compromise good OOP. A good class has data + behaviour, so enumeration members are not sufficiently specialised to represent the concept they are named for. The logic concerning this domain object lives somewhere else other than the entity that bears its name, which I dislike.
Enumerations are meant to convey ordinality, so DaysOfWeek is a good usage (except that which day of the week is 'first' varies depending on culture, but that' nitpicking) because the enumeration denotes the order of its members. In your case, does it make sense to say that a particular value is the 'first' user type, the second value is second, and so on? Probably not.
My first question would be - do you actually use the user type anywhere in the database?
If the answer is no, everything is easier, since you can simply use an enum and be done with it.
Otherwise, you probably should have a user type table as well, to get to use foreign keys properly.
Personally, I use manual ID for these - autogenerated keys can make a mess of your attempts to synchronize code and database. Ideally, if your ORM allows it, you could have the code-database synchronization automatic - either through code generation, or through automatic database data update. If you can't, though, manually coding the enums (or some kind of pseudo enum) should still be a lot nicer in the code.
As for localization, your options are completely the same. Just use a resource key like "UserType-XXX", where XXX is the database ID of the type. If you want, you can also store the localized values in the database. Just do whatever feels the best for your application.
I'm wondering if the following DB schema would have repercussions later. Let's say I'm writing a place entity. I'm not certain what properties of place will be stored in the DB. I'm thinking of making two tables: one to hold the required (or common) info, and one to hold additional info.
Table 1 - Place
PK PlaceId
Name
Lat
Lng
etc... (all the common fields)
Table 2 - PlaceData
PK DataId
PK FieldName
PK FK PlaceId
FieldData
Usage Scenario
I want certain visitors to have the capability of entering custom fields about a place. For example, a restaurant is a place that may have the following fields: HasParking, HasDriveThru, RequiresReservation, etc... but a car dealer is also a place, and those fields wouldn't make sense for a car dealer.
I want to support any type of place, from a single table (well, 2nd table has custom fields), because I don't know the number of types of places that will eventually be added to my site.
Overall goal
On my asp.net MVC (C#/Razor) site, where I display a place, it will show the attributes, as a unordered list populated by: SELECT * FROM PlaceData WHERE PlaceId = #0.
This way, I wouldn't need to show empty field names on the view (or do a string.IsNullOrWhitespace() check for each and every field. Which I would be forced to do if every attribute was a column on the table.
I'm assuming this scenario is quite common, but are there better ways to do it? Particularly from a performance perspective? What are the major drawbacks of this schema?
Your idea is referred to as an Entity-Attribute-Value table and is generally bad news in a RDBMS. RDBMSes are geared toward highly structured data.
The overall options are:
Model the db further in an RDBMS, which is most likely if someone is holding back specs from you.
Stick with the RDBMS, using XML columns for the data whose structure is variable. This makes the most sense if a relatively small portion of your data storage schema is semi- or un-structured. Speaking from a MS SQL Server perspective, this data can be indexed and you can perform checks that your data complies with an XML schema definition.
Move to a non-relational DB such as MongoDB, Cassandra, CouchDB, etc. This is what a lot of social sites and I suspect blog sites run with. Also, it is within reason to use a combination of RDBMS and non-relational stores if that's what your needs call for.
EAV gets to be a mess because you're creating a database within a database and lose all of the benefits a RDBMS can provide (foreign keys, data type enforcement, etc.) and the SQL code needed to reconstruct your objects goes from lasagna to fettuccine to spaghetti in the blink of an eye.
Given the information that's been added to the question, it would seem a good fit to create a PlaceDetails column of type XML in the Place table. You could also split that column into another table with a 1:1 relationship if performance requirements dictate it.
The upside to doing it that way is that you can retrieve the data using very simple SQL code, even using the xml data type's methods for searching the data. But that approach also allows you to do the more complex presentation-oriented data parsing in C#, which is better suited to that purpose than T-SQL is.
If you want your application to be able to create its own custom fields, this is a fine model. The Mantis Bugtracker uses this as well to allow Admins to add custom fields to their tickets.
If in any case, it's going to be the programmer that is going to create the field, I must agree with pst that this is more a premature optimization.
At any given time you can add new columns to the database (always watching for the third normalization rule) so you should go with what you want and only create a second table if needed or if such columns breaks any of the normal forms.
What would be the best database/technique to use if I'd like to create a database that can "add", "remove" and "edit" tables and columns?
I'd like it to be scaleable and fast.
Should I use one table and four columns for this (Id, Table, Column, Type, Value) - Is there any good articles about this. Or is there any other solutions?
Maybe three tables: One that holds the tables, one that holds the columns and one for the values?
Maybe someone already has created a db for this purpose?
My requirements is that I'm using .NET (I guess the database don't have to be on windows, but I would prefer that)
Since (in comments on the question) you are aware of the pitfalls of the "inner platform effect", it is also true that this is a very common requirement - in particular to store custom user-defined columns. And indeed, most teams have needed this. Having tried various approaches, the one which I have found most successful is to keep the extra data in-line with the record - in particular, this makes it simple to obtain the data without requiring extra steps like a second complex query on an external table, and it means that all the values share things like timestamp/rowversion for concurrency.
In particular, I've found a CustomValues column (for example text or binary; typically json / xml, but could be more exotic) a very effective way to work, acting as a property-bag for the additional data. And you don't have to parse it (or indeed, SELECT it) until you know you need the extra data.
All you then need is a way to tie named keys to expected types, but you need that metadata anyway.
I will, however, stress the importance of making the data portable; don't (for example) store any specific platform-bespoke serialization (for example, BinaryFormatter for .NET) - things like xml / json are fine.
Finally, your RDBMS may also work with this column; for example, SQL Server has the xml data type that allows you to run specific queries and other operations on xml data. You must make your own decision whether that is a help or a hindrance ;p
If you also need to add tables, I wonder if you are truly using the RDBMS as an RDBMS; at that point I would consider switching from an RDBMS to a document-database such as CouchDB or Raven DB
I'm looking for a good solution to make my life easier with regards to writing/reading to a SQL Server DB in a dynamic manner. I started with Entity-framework to make my life easier to begin with, but as the software become more general and config driven I'm finding that Entity becomes less and less appropriate because it relies on specific objects defined at design time.
What I'd like to do.
Generate Tables/Fields at runtime.
Select rows from tables by table name with unknown schema into a generic data type (eg Dictionary)
Insert rows to tables by table name using generic data types (dictonary, where the string maps to field name), where the data type mapping between typeof(object) and field type is taken care off.
I've started implementing this stuff myself, but I imagine someone has already has already done it before.
Any suggestions?
Thanks.
I'm having trouble understanding how what you are describing is any different than plain old ADO.NET. DataTables are dynamically constructed based on a SQL query and a DataRow is just a special case of an IndexedDictionary (sometimes called an OrderedDictionary where you can access values via a string name or an integer index like a list). I make no judgment as to whether choosing ADO.NET is actually right or wrong for your needs, but I'm trying to understand why you seem to have ruled it out.
You can use Sql.Net ( http://sqlom.sourceforge.net ) to easily generate dynamic SQL statements in C#.
The iBATIS.NET (now MyBatis.NET) Data Mapper framework doesn't automatically generate tables or fields at runtime, but it does allow you to select and commit data via Dictionary objects.
It's probably not going to suit your needs completely (it's kind of tedious to set up, but pretty easy to maintain once it is), but it might be worth a look. Here's a link to the online documentation.
Other popular frameworks might do the same or similar, such as NHibernate.