C# Enum using values in Sql Server table - c#

At the moment I have a SQL Server 2005 table that looks a bit like:
ID | name | desc
----------------------
1 | ONE | Value One
3 | THREE | Value Three
5 | FIVE | Value Five
This table corresponds with an enum in C# that looks like:
enum MsgTypes{
<summary>Value One</summary>
ONE = 1,
<summary>Value Three</summary>
THREE = 3,
<summary>Value Five</summary>
FIVE = 5
}
So my question is this: Is there a good way to associate the enum to the SQL table so that any changes/additions to the values in the table don't need to be manually made in the c# code?

If you want it to be somewhat dynamic, why make it an enum to start with? Just fetch the details from the table on app startup, and remember them in (say) a Dictionary<int, string>. You could always encapsulate the value within your own value type which enforced the range, if you wanted to.
Alternatively, if you don't mind recompiling, you could fetch it at build time and autogenerate the enum source code.

I had to have a think about something similar recently (refactoring an enum) -- basically I considered using a Dictionary<A, B> to store the enum values in. You could dynamically load from the table to populate the dictionary if you wanted to.
One thing I'd add -- is if you're replacing an enum that already exists with something dynamic you'll have to think about what you're going to do with exceptions raised as part of populating it dynamically.

To me it depends on how often the enums/DB lookup tables change. We have about a half dozen enum/lookups like this in our system, and i don't mind recompiling to add an emum option + DB row becuase:
It doesn't happen very often - probably twice in the past year that i can think of
There is usually new business logic surrounding the new option so coding is necessary anyway.

Another alternative would to implement a custom object with ID, Name, and Desc properties that would encapsulate the database table.

I accept with what Jon is suggesting, but then if you prefer to have your Enum list in the DB and want to use them in your code, you could use TypeTable feature from nHydrate for your project.

Related

C# how to correctly use dictionary in Database and code?

I think I got an architecture problem.
For the example purpose let's say I have a table named Dict.Country with two columns : Id and Name like below. The reason why I have such a table and not only Enum in code is because with time we want to dynamically add another values.
1 USA
2 POLAND
3 CHINA
etc.
So now is the question, how to correctly read and operate on these values? I can create class DictElement with string fields Id and Column, then read them from database and operate, but we got the problem that we have to operate on strings literals:
if (x.country == "POLAND")
...
which I believe is bad practice, cause one small misspelling can make us much troubles.
Is there any good practice how to work on such dictionaries from database?

hardcoding primarykey value in applications

Hi I came to this situation working in my project, where people hardcode the value of a primarykey column in an application. Is it a good practice. while dealing with environments the value of that record might change but how about using identity inserts to other environments.
While this is obviously a very poor practice, I hesitate to reject anything like this without decent information on the reasoning. I usually give my colleagues the benefit of the doubt and assume they have thought about the problem and come to a reasonable conclusion, and I simply need to learn to understand their reasoning.
There are certain very rare cases where hardcoded identities can be an OK solution, for example if your installation package also creates the database and the schema and seeds certain domain lookup values so they are the same on every system. In cases like these, the identity column is defined with a seed that is a little higher than usual (e.g. IDENTITY(100,1)) and the system values are always placed below the seed (in this case, 100).
For example, maybe you have a domain table for PhoneType and values 1-3 are reserved for "Primary," "Billing," and "Contact." Meanwhile values 100 and up are allowed for end users to define their own phone types.
It is definitely a poor practice to insert hardcoded identity values during run-time proper, e.g. in response to user input. In that case it is probably better to find a natural key, use a GUID, or develop your own identity tracking system.
Typically I've seen this where there are constants in the code base (like enums for some kind of basic system types which are fundamental to the application) that are also in the database (as lookup tables). There are some better ways to handle this, but ultimately, something is always going to get hardcoded in these cases, even if it isn't the primary key. A primary key might be a natural key, for instance.
Typically you would only see this being acceptable for very fundamental entities. Perhaps a type of organization or entity in a program like: TYPE_USER, TYPE_GROUP. You would not see this for lookups which are typically user-modifiable, or expecting to be extensible, or not fundamental in some way, like VEHICLE_TYPE_CAR, VEHICLE_TYPE_SUV, VEHICLE_TYPE_RV, VEHICLE_TYPE_MOTORCYCLE, etc.
In any case, it is a code smell, and it's not a practice that's a good idea unless it's a fundamental immutable enumeration in the architecture.
I agree with all the replies here thus far and I also face certain situations where I need to check a condition on a certain value that is based on the primary key. As Siyual has stated, checking for this condition against a more explanatory field makes more sense.
One way of dealing with this could be to add another column in the entity describing the row, and use that as a conditional check that gets mapped to an enum.
e.g. Table:
+-----+----------+-------------+
| PK | Status | Enum_mapped |
+-----+----------+-------------+
| 101 | Fitted | 1 |
| 201 | Unfitted | 2 |
| 301 | Used | 3 |
+-----+----------+-------------+
Code:
private enum Statuses
{
Fitted,
Unfitted,
Used
}
private int GetStatus(int enumstatus)
{
return enumstatus = ctx.myStatus.Where(a => a.Enum_mapped == enumstatus).Select(a => a.PK).FirstOrDefault();
}
Call the appropriate status:
GetStatus((int)Statuses.Fitted);
Result = 101

SQL good practices and foreign key

I have to create a database structure. I have a question about foreing keys and good practice:
I have a table which must have a field that can be two different string values, either "A" or "B".
It cannot be anything else (therefore, i cannot use a string type field).
What is the best way to design this table:
1) create an int field which is a foreign key to another table with just two records, one for the string "A" and one for the string "B"
2) create an int field then, in my application, create an enumeration such as this
public enum StringAllowedValues
{
A = 1,
B
}
3) ???
In advance, thanks for your time.
Edit: 13 minutes later and I get all this awesome feedback. Thank you all for the ideas and insight.
Many database engines support enumerations as a data type. And there are, indeed, cases where an enumeration is the right design solution.
However...
There are two requirements which may decide that a foreign key to a separate table is better.
The first is: it may be necessary to increase the number of valid options in that column. In most cases, you want to do this without a software deployment; enumerations are "baked in", so in this case, a table into which you can write new data is much more efficient.
The second is: the application needs to reason about the values in this column, in ways that may go beyond "A" or "B". For instance, "A" may be greater/older/more expensive than "B", or there is some other attribute to A that you want to present to the end user, or A is short-hand for something.
In this case, it is much better to explicitly model this as columns in a table, instead of baking this knowledge into your queries.
In 30 years of working with databases, I personally have never found a case where an enumeration was the right decision....
Create a secondary table with the meanings of these integer codes. There's nothing that compels you to JOIN that in, but if you need to that data is there. Within your C# code you can still use an enum to look things up but try to keep that in sync with what's in the database, or vice-versa. One of those should be authoritative.
In practice you'll often find that short strings are easier to work with than rigid enums. In the 1990s when computers were slow and disk space scarce you had to do things like this to get reasonable performance. Now it's not really an issue even on tables with hundreds of millions of rows.

model classes in a database with my own enum types

I have an application that I need to query lifetables (for insurance calculation).
I was thinking about using XML to store the data, but thought it was a little big, but maybe a little small for using a full-fledged database. So I chose to use SQLite.
In my application, I have enums defining a few different things. For example, GENDER.Male, GENDER.Female. and JOBTYPE.BlueCollar, JOBTYPE.WhiteCollar. etc etc.
I have some methods that look like this: (example)
FindLifeExpectancy(int age, GENDER gender);
FindDeathRate(int age, JOBTYPE jobType);
So my question is: How do you model enums in a database? I don't think it is best practice to use 0 or 1 in the database to store JOBTYPE because that would be meaningless to anyone looking at it. But if you used nvarchar, to store "BlueCollar", there would be a lot of duplicate data.
I don't think GENDER or JOBTYPE should have an entire class, or be apart of the entity model because of the little information they provide.
How is this normally done?
Thanks.
I prefer to statically map my enums in my program to a lookup table in my database. I rarely actually use the lookup table to do a join. As an example I might have the following tables:
Gender
GenderID Name
1 Male
2 Female
Accounts
AccountID GenderID FirstName LastName
1 1 Andrew Siemer
2 2 Jessica Siemer
And in code I would then have my enum defined with the appropriate mapping
public enum Gender
{
Male = 1,
Female = 2
}
Then I can use my enum in code and when I need to use the enum in a LINQ to SQL query I just get its physical value like this
int genderValue = (int)Enum.Parse(typeof(Gender), Gender.Male));
This method may make some folks out there a bit queezy though given that you have just coupled your code to values in your database! But this method makes working with your code and the data that backs that code much easier. Generally, if someone swaps out the ID of a lookup table, you are gonna be hosed in some way or another given that it is mapped across your database any how! I prefer the readability and ubiquitous nature of this design though.
While it's unlikely that you will be adding a new gender, I wouldn't be so sure about the jobtype enum. I'd have used a separate table for both, and have foreign keys to this table every where I need to reference them. The schema will be extensible, the database will automatically check that only possible values are saved in the referencing tables.
The SQL equivalent of 'enums' are lookup tables. These are tables with two (sometimes more) columns:
a code, typically short, numeric or character (ex: 'R', 'S', 'M'...)
a text definition (ex: 'Retired', 'Student', 'Military'...)
extra columns can be used to store definitions, or alternate versions of the text for example a short abbreviation for columnar reports)
The short code is the type of value stored in the database, avoiding the replication you mentioned. For relatively established categories (say Male/Female), you may just use a code, without 'documenting' it in a lookup table.
If you have very many different codes, it may be preferable to keep their lookup in a single SQL table, rather than having a proliferation of dozen of tables. You can simply add a column that is the "category", which itself is a code, designating the nature of the group of codes defined in this category ("marital status", "employment", "education"...)
The info from the lookup tables can be used to populate drop downs and such, in the UI, wherey the end-user sees the clear text but the application can use the code to query the database. It is also used in the reverse direction, to produce the clear text for codes found in the database, for displaying results list and such.
A JOIN construct at the level of SQL is a convenient way to relate the lookup table and the main table. For example:
SELECT Name, Dob, M.MaritalStatus
FROM tblCustomers C
LEFT OUTER JOIN tblMaritalLkup M ON C.MStatus = M.Code
WHERE ...

Auto generation of ID

I need to generate an id with the
following features:
Id must be unique
Id consist of two parts 'type' and 'auto incremented' number
'type' is integer and value can be 1, 2 or 3
'auto incremented' number starts with 10001 and incremented each time id
is generated.
type is selected from a web form and auto incremented number
is from the database.
Example: if type is selected 2 and auto incremented number is 10001
then the generated id is = 210001
There may be hundrads of users generating id. Now my question is,
Can this be done without stored procedure so that there is no id confict.
I am using ASP.Net(C#), Oracle, NHibernate
As you use Oracle, you can use a Sequence for that.
Each time you call your_sequence.NEXTVAL, a unique number is returned.
Why isn't the NHibernate implementation of Hi-Lo acceptable?
What’s the Hi/Lo Algorithm
What's the point in having the first digit of the ID to define the type? You should use a separate column for this, and then just use a plain auto-incrementing primary key for the actual ID.
The cleanest way is - as Scott Anderson also said - to use two columns. Each attribute should be atomic, i.e. have only one meaning. With a multi-valued column you'll have to apply functions (substr) to reveal for example the type. Constraints will be harder to define. Nothing beats a simple "check (integer_type in (1,2,3))" or "check (id > 10000)".
As for defining your second attribute - let's call it "id" - the number starting from 10001, you have two good strategies:
1) use one sequence, start with 1, and for display use the expression "10000 + row_number() over (partition by integer_type order by id)", to let the users see the number they want.
2) use three sequences, one for each integer_type, and let them have a start with clause of 10001.
The reason why you should definitely use sequences, is scalability. If you don't use sequences, you'll have to store the current value in some table, and serialize access to that table. And that's not good in a multi user system. With sequences you can set the cache property to reduce almost all contention issues.
Hope this helps.
Regards,
Rob.
If you can't use auto incrementing types such as sequences, have a table containing each type and keeping score of its current value. Be careful to control access to this table and use it to generate new numbers. It is likely it will be a hot spot in your db though.

Categories

Resources