When to use Enums with Entity Framework? - c#

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.

Related

translate large queries to linq to Entity framework

I have a few very large queries which I need to convert it linq because we are using Entity framework and I cant use stored procedures(breaks compatibility with other data bases).
using tool like linqer didnt even help and even if I get it to work with some mods to generated linq, there is a huge performance issue.
so, what is the best option in a situation like this where EF fails?
please don't ask me to divide it into small queries cause that's not possible.
Moving this to an "answer" because what I want to say is too long for a comment.
It sounds like you're running into an inherent limitation to ORMs. You won't get perfect performance trying to do everything in code. It sounds like you're trying to use an ORM like a T-SQL interface rather than a mapping between objects and a relational instance of data.
You say you want to maintain compatibility between databases but that's already a nonstarter if you consider schema differences from database to database. If you're already implementing a schema validation step so you ensure your code doesn't break, then there should be no reason why you can't use something like views.
You can say you don't want to support these things all day long but the simple point is that these things exist because they address certain problems. If you wholesale abandon them, then you can't really expect to get rid of the problem. Some things the database simply does better.
So, I think you're expecting something out of the technology that it wasn't meant to solve. You'll need to either reevaluate your strategy or use another tool to accomplish it. I think you may even need a couple different tools.
What you've been doing may have worked when your scale was smaller. I could see such a thing working for quite a while actually. However, it does have a scale limit, and I think you're coming up against it.
I think you need to make a determination on what databases you want to support. Saying "we support all databases" is untenable. Then, compare features and use the ones in common. If it's a MS SQL vs. MySQL thing, then there's no reason why you can't use views or stored procedures.
Check out LinqKit - this is a very useful tool for building up complex large EF queries.
http://www.albahari.com/nutshell/linqkit.aspx

Best practice : use enum or not to store dropdown values

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.

List to Database

I might be way off here, and this question probably bordering subjective, but here goes anyway.
Currently I use IList<T> to cache information from the database in memory so I can use LINQ to query information from them. I have a ORM'ish layer I've written with the help of some questions here on SO, to easily query the information I need from the DB. For example:
IList<Customer> customers = DB.GetDataTable("Select * FROM Customers").ToList<Customer>();
Its been working fine. I also have extension methods to do CRUD updates on single items within these lists:
DB.Update<Customer>(customers(0));
Again working quite well.
Now in the GUI layer of my app, specifically when binding DataGridView's for the user to edit the data, i find myself bypassing this DAL layer and directly using TableAdapters within the forms which kind of breaks the layered architecture which smells a bit to me. I've also found the fact that I'm using TableAdapters here and ILists there, there are differing standards followed throughout my code which I would like to consolidate into one.
Ideally, I would like to be able to bind to these lists and then have the DAL update the list's 'dirty' data for me. To me, this process would involve the following:
Traversing the list for any 'dirty' items
For each of these, see if there is already an item with the PK in the DB
If (2), then update, else insert
Finally, perform a Delete FROM * WHERE ID NOT IN('all ids in list') query
I'm not entirely sure how this is handled in a TableAdapter, but I can see the performance of this method dropping significantly and quite quickly with increasing items in the list.
So my question is this:
Is there an easier way of committing List to a database? Note the word commit, as it may be an insert/update or delete.
Should I maybe convert to DataTable? e.g. here
I'm sure some of the more advanced ORM's will perform this type of thing, however is there any mini-orm (e.g. dapper/Petapoco/Simple.data etc) that can do this for me? I want to keep it simple (as is with my current DAL) and flexible (I don't mind writing the SQL if its gets me exactly what I need).
Currently I use IList to cache information from the database in memory so I can use LINQ to query information from them.
Linq also has a department called Linq-to-Datasets so this is not a compelling reason.
Better decide what you really want/need:
a full ORM like Entity Framework
use DataSets with DataDapters
use basic ADO.NET (DataReader and List<>) and implement your own change-tracking.
You can mix them to some extent but like you noted it's better to pick one.

Generate Enums from Database or Vice Versa?

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.

Need advice on combining ORM and SQL with legacy system

We are in the process of porting a legacy system to .NET, both to clean up architecture but also to take advantage of lots of new possibilities that just aren't easily done in the legacy system.
Note: When reading my post before submitting it I notice that I may have described things a bit too fast in places, ie. glossed over details. If there is anything that is unclear, leave a comment (not an answer) and I'll augment as much as possible
The legacy system uses a database, and 100% custom written SQL all over the place. This has lead to wide tables (ie. many columns), since code that needs data only retrieves what is necessary for the job.
As part of the port, we introduced an ORM layer which we can use, in addition to custom SQL. The ORM we chose is DevExpress XPO, and one of the features of this has also lead to some problems for us, namely that when we define a ORM class for, say, the Employee table, we have to add properties for all the columns, otherwise it won't retrieve them for us.
This also means that when we retrieve an Employee, we get all the columns, even if we only need a few.
One nice thing about having the ORM is that we can put some property-related logic into the same classes, without having to duplicate it all over the place. For instance, the simple expression to combine first, middle and last name into a "display name" can be put down there, as an example.
However, if we write SQL code somewhere, either in a DAL-like construct or, well, wherever, we need to duplicate this expression. This feels wrong and looks like a recipe for bugs and maintenance nightmare.
However, since we have two choices:
ORM, fetches everything, can have logic written once
SQL, fetches what we need, need to duplicate logic
Then we came up with an alternative. Since the ORM objects are code-generated from a dictionary, we decided to generate a set of dumb classes as well. These will have the same number of properties, but won't be tied to the ORM in the same manner. Additionally we added interfaces for all of the objects, also generated, and made both the ORM and the dum objects implement this interface.
This allowed us to move some of this logic out into extension methods tied to the interface. Since the dumb objects carry enough information for us to plug them into our SQL-classes and instead of getting a DataTable back, we can get a List back, with logic available, this looks to be working.
However, this has lead to another issue. If I want to write a piece of code that only displays or processes employees in the context that I need to know who they are (ie. their identifier in the system), as well as their name (first, middle and last), if I use this dumb object, I have no guarantee by the compiler that the code that calls me is really providing all this stuff.
One solution is for us to make the object know which properties have been assigned values, and an attempt to read an unassigned property crashes with an exception. This gives us an opportunity at runtime to catch contract breaches where code is not passing along enough information.
This also looks clunky to us.
So basically what I want advice on is if anyone else has been in, or are in, this situation and any tips or advice you can give.
We can not, at the present time, break up the tables. The legacy application will still have to exist for a number of years due to the size of the port, and the .NET code is not a in-3-years-release type of project but will be phased in in releases along the way. As such, both the legacy system and the .NET code need to work with the same tables.
We are also aware that this is not an ideal solution so please refrain from advice like "you shouldn't have done it like this". We are well aware of this :)
One thing we've looked into is to create an XML file, or similar, with "contracts". So we could put into this XML file something like this:
There is an Employee class with these 50 properties
Additionally, we have these 7 variations, for various parts of the program
Additionally, we have these 10 pieces of logic, that each require property X, Y and Z (X, Y and Z varies between those 10)
This could allow us to code-generate those 8 classes (full class + 7 smaller variations), and have the generator detect that for variation #3, property X, Y and K is present, and I can then tie in either the code for the logic or the interfaces the logic needs into this class automagically. This would allow us to have a number of different types of employee classes, with varying degrees of property coverage, and have the generator automatically add all logic that would be supported by this class to it.
My code could then say that I need an employee of type IEmployeeWithAddressAndPhoneNumbers.
This too looks clunky.
I would suggest that eventually a database refactoring (normalization) is probably in order. You could work on the refactoring and use views to provide the legacy application with an interface to the database consistent with what it expects. That is, for example, break the employe table down in to employee_info, employee_contact_info, employee_assignments, and then provide the legacy application with a view named employee that does a join across these three tables (or maybe a table-based function if the logic is more complex). This would potentially allow you to move ahead with a fully ORM-based solution which is what I would prefer and keep your legacy application happy. I would not proceed with a mixed solution of ORM/direct SQL, although you might be able to augment your ORM by having some entity classes which provide different views of the same data (say a join across a couple of tables for read-only display).
"We can not, at the present time, break up the tables. The legacy application will still have to exist for a number of years due to the size of the port, and the .NET code is not a in-3-years-release type of project but will be phased in in releases along the way. As such, both the legacy system and the .NET code need to work with the same tables."
Two words: materialized views.
You have several ways of "normalizing in place".
Materialized Views, a/k/a indexed views. This is a normalized clone of your source tables.
Explicit copying from old tables to new tables. "Ick" you say. However, consider that you'll be incrementally removing functionality from the old app. That means that you'll have some functionality in new, normalized tables, and the old tables can be gracefully ignored.
Explicit 2-way synch. This is hard, not not impossible. You normalize via copy from your legacy tables to correctly designed tables. You can -- as a temporary solution -- use Stored Procedures and Triggers to clone transactions into the legacy tables. You can then retire these kludges as your conversion proceeds.
You'll be happiest to do this in two absolutely distinct schemas. Since the old database probably doesn't have a well-designed schema, your new database will have one or more named schema so that you can maintain some version control over the definitions.
Although I haven't used this particular ORM, views can be useful in some cases in providing lighter-weight objects for display and reporting in these types of databases. According to their documentation they do support such a concept: XPView Concepts

Categories