Entity Framework 5 Enum that is built from a db table - c#

I have those two entities :
Color entity is mapped to a table of constant values that represent colors.
Code=1, Name="Red"
Code=2, Name="Blue"
And so on...
In Car entity, the Color property is of type int and has a foreign key constraint to the Code property in Color entity. I want to convert the Color property in Car to an Enum, but the Enum should get it's values from Color table.
The Enum could be updated in each build action or an "update model" action in the designer.
Can this functionality can be achieved ?

" but the Enum should get it's values from Color table. "
So whats wrong with what you have? Anyway since you asked...
An enum is by definition inside the assembly. So as soon as a new color is added to the table you have an outdated Enum. But if you are ok with having upto date at build time. There is a good option.
Clearly the suggestion to use T4 is interesting . But the t4 would need to connect to DB and read it. When T4 goes beyond source generation, it can be easier to use a simple app. Unless of course you are already good at t4. So if t4 is a little hard for this task try:
A simple side app, that reads the DB and updates the EnumColor.cs would be plausible.
IE a simple console app. Place as a pre build step. The pre-build reads the DB, rewrites the enum.cs file and the compile/build then follows.
**Easy Alternative: using a Dictionary which you can extend at runtime **
Dictionary<int,string> colors

For me the first question is why? I had a similar technical need but the business need was to help with reporting. Enums works great to make code simpler to read and maintain, but is you have to create a report in say SSRS then you don't have access to the enums (okay I am sure some advanced SSRS users will say you can link in assemblies etc, but that is not the point). We played a bit with a prebuild script (could also run post build) to generate inline scaler function scripts to execute against the db. This way you could do select statements such as:
SELECT Model, fColorNameEnum(Color) FROM Car
This way you do not have to touch you reports again if you add a new element in your enum. I tend to use enums in the implementation of business logic, typically item status or workflow state. Adding a new option thus require adding new logic which means doing it in code. If you are never going to reason over the color value in code, then what is the reason for wanting to put it in an enum rather than just another linked object?

Related

At runtime replace enum values in C# file in dll

I have written a dll in C# which has five .cs files. ControlsOnForm.cs has a public enum defined in it.
public enum FormControls {
Button,
Label,
DataGrid,
TextBox
}
Now, I'm using this dll in a Windows app which is shown in attached Image1 and when I click Generate button it generates the ControlsOnForm.cs C# file which is same as the enum in dll.
Now how do I refer/use this dynamically generated C# file with enum values in dll.
Or in another words the enum values in ControlsOnForm.cs of dll should get replaced with the newly generated C# file's enum values.
Thanks,
Although it is trivial to get your code to generate a cs file. I suspect what you then want to do is run the resulting code. That step is highly difficult and there are many things you need to understand in terms of the limitation.
However as another user has commented, it sounds like what you want to change is data, and not code.
You should understand the distinction between hardware, firmware, code, configuration and data. The lines are much more blurred than you might first think. But at the end of the day, each is a step in a continuum of changeability. For your purpose, code should be the thing that changes the least often. This in our tool chain it is the hardest to change. Remember at the end of the day everything is ones and zeros... and your data should also change how your program works.
Enums are a collection of named constants. In the same sense that you cannot change a constant, you cannot change an enum (at least without jumping through a ton of hoops).
What you really want to do here is use an external dataset, be it a datatable, an XML configuration file, etc.
On a side note, you would probably want to create an enum outside of a form, but in the same namespace. You can add a module to a project and drop all your enums in there.
From MSDN:
The enum keyword is used to declare an enumeration, a distinct type
that consists of a set of named constants called the enumerator
list.
Usually it is best to define an enum directly within a namespace so
that all classes in the namespace can access it with equal
convenience. However, an enum can also be nested within a class or
struct.
Reference: MSDN Enum Entry

Structural change in an Asp.Net MVC application backed by sprocs

Hello fellow developers.
First of all I apologize beforehand for the wall of text that follows, but after a day going crazy on this, I need to call for help.
I've stumbled across a problem I cannot seem to solve. I'll try to describe the scenario in the best possible way.
Task at hand: in an existing Asp.Net Mvc application, create a lookup table for an integer field, and use the textual value from the lookup in the editing view. When saving, we must first check if the lookup already has a corresponding text value for the same Root ID. If there is, use that. Otherwise, create it and then use it.
The structure:
The data model is a graph of objects where we have the root object, a collection of level A child objects, and every level A child object has a collection of level B child objects, so something like this:
Root (with fields)
Level A child (with fields) x n
Level B child (with fields) x n
The field we have to handle is on the LevelB objects.
There is a single Mvc view that handles the whole data. For collection objects, all fields are named like levelA1levelB1MyField, levelA1levelB2MyField, etc so every single field has unique name during the post. When the post happens, all values are read through a formCollection parameter which has average 120/130 keys. The keys are isolated by splitting them and looping on the numerical part of the names, values are read and parsed to the expected types and assigned to the object graph.
The datalayer part backing the object graph is all stored procedures, and all the mapping (both object to sproc and sproc to object) is hand written. There's a single stored procedure for the read part, which gets multiple datasets, and the method calling it reads the datasets and creates the object graph.
For the saving, there are multiple sprocs, mainly a "CreateRoot" and "UpdateRoot". When the code has to perform such tasks, the following happens:
For create scenario, "CreateRoot" is called, then the sprocs "CreateLevelA" and "CreateLevelB" are called in loop for each element in the graph;
For update scenario, "UpdateRoot" is called, which internally deletes all "LevelA" and "LevelB" items, then the code recreates them calling the aforementioned sprocs in loop.
Last useful piece of information is that the "business objects graph" is used directly as a viewmodel in the view, instead of being mapped to a plain "html friendly" viewmodel. This is maybe what is causing me the most trouble.
So now the textbox on the view handles an "integer" field. That field must now accept a string. The field on LevelB must remain an integer, only with a lookup table (with FK of course) and the text field from the lookup must be used.
The approaches I tried with no success:
My first thought was to change the datatype on the property MyField from integer to string on the object, then change the sprocs accordingly and handle the join at sproc level: I'd have a consistent object for my view, and the read/write sprocs could translate from string to integer and viceversa, but I can't do that because the join keys to retrieve the integer when writing are part of the Root item (as I stated in the first lines of this wall of text), which I don't know in the CreateLevelB sproc, and changing the whole chain of calls to pass those parameters would have a huge impact on the rest of the application, so no good.
My next try was to keep things "as they are" and call some "translation methods": when reading, pass the integer to the view, and there call the translation method to display the text value. When saving, use the posted text to retrieve the integer. The save part would work, I'd have all the parameters I need, but for the read part, I'd have to instantiate the "data access layer" and call its method at View level, and there's no need to explain why that is a very bad choice, so I ruled this out too.
Now I'm out of options (or ideas anyway). Any suggestion to solve this is very welcome, and also if something is not clear enough just point it out and I will edit my post with more accurate information.
Thanks.
This is not a real answer but you could rip out all sprocs and use the updating facilities of an OR mapper. This will resolve all the layering issues. You just update data how you see fit and submit at the end.
I guess this would also make the questions around "should I use an int or a string" go away.
Edit: After reading your comment I thought of the following: Do not implement alternative 1. You rather want to sacrifice code quality in the view than in the data storage model. The last one is more important and more centrally used.
I would not be too concerned with messing up the view by calling the DAL from it or the like. Changes in a view are localized and do not mess up the application's architecture. They just degrade the view.
Maybe you could create a view model in your controller and do the translations between DAL-model and view model? Or is that pattern not allowed?

Creating an enum/class from a Database Table

I have a database table that essentially contains different types of things. I'll use animals as an example. I have a table called AnimalTypes:
AnimalTypes
{
ID:int,
Name:string
}
I then populate it with:
1:Dog,
2:Cat,
3:Fish
I would like to then have some sort of C# object created that functions similar to this enum be entirely read from the database:
enum AnimalTypes
{
Dog = 1,
Cat = 2,
Fish = 3
}
Is there a way to create an enum/class from a database table as described? I basically want to be able to reference things in the AnimalTypes table using intellisense and AnimalTypes.Dog as an example; I don't actually need an enum, just something that kind of functions like one. Is this possible?
Edit: I'm not really that thrilled about generating a DLL as I've seen in other related problems. I feel like this should be possible with reflection.
Lets suppose I don't need intellisense.
You will have to generate an assembly if you want to be able to use the enumeration or class at compilation time. Reflection happens at execution time so that won't give you intellisense.
This is a common problem - there are a set of distinct values in a database table and those values don't change often so they are modeled as an enum in the source code. This allows these somewhat static values to be easily used in a very readable way. The problem is that when the values do change, it would be nice if the enum changed as well.
The problem with trying to keep the enum and database in sync is that an automatic process doesn't change the fact that if you are changing the database it would be very unlikely that you would do so without having to roll new code to leverage the changed value. It is better to model these values as an enum and still store them in the database. Just manually sync them as the need arises.
Try this solution:
"Creating Enums from database lookup tables"
using T4 code generation for lookup tables.
There's always code generation: http://www.mygenerationsoftware.com/ if you don't want to go the reflection route.

C# Factory Pattern

I am building a search application that has indexed several different data sources. When a query is performed against the search engine index, each search result specifies which data source it came from. I have built a factory pattern that I used to display a different template for each type of search result, but I've realized that this pattern will become more difficult to manage as more and more data sources are indexed by the search engine (i.e new code template has to be created for each new data source).
I created the following structure for my factory based off of an article by Granville Barnett over at DotNetSlackers.com
factory pattern http://img11.imageshack.us/img11/8382/factoryi.jpg
In order to make this search application easier to maintain, my thought was to create a set of database tables that can be used to define individual template types that my factory pattern could reference in order to determine which template to construct. I figured that I'd need to have a look up table that would be used to specify the type of template to build based off of the search result data source. I'd then need to have a table(s) to specify which fields to display for that template type. I'd also need a table (or additional columns within the template table) that would be use to define how to render that field (i.e. Hyperlink, Label, CssClass, etc).
Does anyone have any examples of a pattern like this? Please let me know.
Thanks,
-Robert
I would offer that this proposed solution is no less maintainable than simply associating a data source to the code template, as you currently have now. In fact, I would even go so far as to say you're going to lose flexibility by pushing the template schema and rendering information to a database, which will make your application harder to maintain.
For example, let's suppose you have these data sources with attributes (if I'm understanding this correctly):
Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }
You then may have one of each of these data sources in your search results. Each element is rendered differently (Picture may be rendered with a preview image anchored to the left, or Song could display the album cover, etc.)
Let's just look at the rendering under your proposed design. You're going to query the database for the renderings and then adjust some HTML you are emitting, say because you want a green background for Documents and a blue one for Pictures. For the sake of argument, let's say you realize that you really need three background colors for Songs, two for Pictures, and one for Documents. Now, you're looking at a database schema change, which is promoted and pushed out, in addition to changing the parameterized template you're applying the rendering values to.
Let's say further you decide that the Document result needs a drop-down control, the Picture needs a few buttons, and Songs need a sound player control. Now, each template per data source changes drastically, so you're right back where you started, except now you have a database layer thrown in.
This is how the design breaks, because you've now lost the flexibility to define different templates per data source. The other thing you lose is having your templates versioned in source control.
I would look at how you can re-use common elements/controls in your emitted views, but keep the mapping in the factory between the template and the data source, and keep the templates as separate files per data source. Look at maintaining the rendering via CSS or similar configuration settings. For making it easier to maintain, considering exporting the mappings out as a simple XML file. To deploy a new data source, you simply add a mapping, create the appropriate template and CSS file, and drop them in to expected locations.
Response to comments below:
I meant a simple switch statement should suffice:
switch (resultType)
{
case (ResultType.Song):
factory = new SongResultFactory();
template = factory.BuildResult();
break;
// ...
Where you have the logic to output a given template. If you want something more compact than a long switch statement, you can create the mappings in a dictionary, like this:
IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.
Then, instead of a switch statement, you can do this one-liner:
template = TemplateMap[resultType].CreateTemplate();
My main argument was that at some point you still have to maintain the mappings - either in the database, a big switch statement, or this IDictionary instance that needs to be initialized.
You can take it further and store the mappings in a simple XML file that's read in:
<TemplateMap>
<Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
<!-- ... -->
</TemplateMap>
And use reflection et. al. to populate the IDictionary. You're still maintaining the mappings, but now in an XML file, which might be easier to deploy.

Extending enums via user input

I have the below enum that I use for one of my filters and suit well to my object model
public enum ColorGroups
{
White = 1,
Brown = 2,
Red = 3,
Black = 4
}
My concern is in the future when a client want to another color to the collection how do I extend the collection. I want the system to be fully dynamic and does not require a technical person to alter the code for such things..
If you want the data to be user-editable, it may not be suitable to use an enum. Enums are compile-time units, so will require a developer (or some hacky code generation).
Instead, consider using a database table for this data, pre-populated with your items (and perhaps with a "System" column to control which ones are user-defined vs required by the system). Then changes are just inserts (etc) to the table.
You can, of course, use any other storage mechanism - for example, a delimited string in a config file - but I'm guessing you'll want a database somewhere in the system?
An enum may not be the right tool for the job in that case. You would be better off using a set of configuration options. These could be in a config file, in the registry or in a database, depending upon what is available to you and whether you want the configuration to be undertaken by a developer or consultant, or by the users of the system.
I want the system to be fully dynamic and does not require a technical person to alter the code for such things..
"Fully dynamic" and "use an enum" are mutually exclusive if you don't want a technical person to have to get involved to make changes. A database or a configuration file is a better choice here.

Categories

Resources