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.
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 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.
I've added enums to my C# Entity Framework 6, MVC 4 application. I like the approach as:
I think my model is clear that the value comes from a lookup.
I can easily bind them to a select list in my view using approached such as these: examples from Stack Overflow.
I'm not looking up the database to get the values.
I have less plumbing code to use the values.
On the downside, I'm thinking that:
I need to be careful to keep my database in sync with my code for actual lookup tables.
I guess, I would need to deploy the code every time I make a change to one, instead of perhaps having 'administration' tables where a user could add new lookup values. (I guess you could be selective and not use enums for values that would change a lot).
I'm just wondering what the real advantages of this approach are and if there are common scenarios when I would want to avoid it?
Thanks
I don't think your question is related to EF at all, it's more backend-agnostic.
The only real problem is what you have already suggested - having to recompile when you need to add/remove values. However, that all really depends on how often you actually expect the list to change.
The point of using an enum is for readability & simplicity from the developers perspective, however, if you enum is really just for UI purposes I'd argue that you could end up giving the developer more work in maintaining the list than doing a lot of work once and not having to worry about it again.
Having to re-compile just for the sake of adding a new option for a user seems very brittle to me.
I'm going to code a housekeeping book
So I create properties in code like Name, Category and some other need to create at run-time.
So how should I save that human-readable in a SQL Server database?
My suggestion is to create a table called Properties with 2 columns (Id, Name) and in that table I can store all my properties but it wouldn't anymore human-readable
I also not sure if it will be wise to create a column for each property in one big table
I could also create a XML "file" and store this in my DB but i don't thing this is a good idea either
Any advice is greatly appreciated
There are basically three approached to this
A column for every value
The one you are suggesting which is called an Entity Attribute Value model
Or the one you discounted which would be xml (or serialised objects)
They all have pros and cons, and some of the cons can get quite severe.
A column for every value means you have to change your db and model every time you want to store more data, which makes it very fragile and high maintenance.
EAV can easily lead to the queries becoming huge joins, and imposing data integrity on it is a hiding to nothing.
Object based can also lead to significant optimisation and maintenance issues, having to open every object to see if something is in it, for instance.
Now any one of these might be the best of a bad lot at the time you make the decision (they are all fragile in one respect or another), IF you insist on using a relational database.
Look at one of the NoSQL alternatives, they are designed for this sort of data.
I'm trying to figure out which is the the "correct" way to do this. I have a bunch of lookup tables in my database and would like to place an enum on top of those values so, when coding, it's easier to read (as well as not use hard-coded values).
I'm wondering if I should generate my table values based on an existing enumeration or if I should generate my enumeration from my table's values.
EDIT
Based on the first couple of comments, here are some clarifications:
Frequency of changes to the values could be rather frequent as they are intended to be rather dynamic. That being said, a compile will be necessary before adding any of these either way, because the enumeration needs to be updated to expose the new values.
The main reason for this need is because we don't want to tie people down to a specific list of values, we would like the applications to have the ability to add new entries as and when they need to.
In the past, we have generated the data from enumerations, but I'm second guessing myself
We usually generate enums from the database. We use CodeSmith, which allows us to create project files that can easily regenerate the enums as needed.
We've gone the other way occasionally, usually for reporting purposes (when existing enum values are persisted).
And, of course, we have enums whose values are never persisted.
In general the only reason to generate enums from the database is if code needs to make decisions based on them. If you just want to populate a ComboBox and persist the user's choice, don't generate an enum.
Obviously making decisions based on enums (or strings) whose values can change is fragile. You may want to consider including expiration dates (or "from" and "through" dates) in your database schema, so that existing values are not deleted. Filter expired values when populating UI selectors. This also makes it easier to have referential integrity.
As always in C#, you have to be aware that enum values may fall outside of the expected range. Include a default on your switch.
We came up with helper classes for creating cached lookup lists that make these easier to use.
I'm not advocating going down this route. If you have to, this is how we did it.
There's also a third option in that you have a explicit model which describes the schema in the level of detail you require and then you generate both data & schema from that model.
Regarding your question I think what you should do is thinking about the problem in your context and list pros/cons for you with each alternative and decide on what makes most sense for you and your business.
I have worked worked with all three strategies for different applications, the one I personally prefer is having an explicit model buts depending on the context.
Sorry for being fuzzy but I think for these kind of questions there's real golden rule which always applies in all cases.