We're working on an hospital information system that is being written on C# and using NHibernate to map objects to database. MVC pattern is being used to separate business logic from UI. Here is the problem,
How do you get variable sized different set of strings to UI?
For example a Contact object have a property named City that holds which city contact lives. In country that the app is written for has more than 80 cities. How could you write those cities to a combo box? (or a data grid, tables, ...) In this example the city number is fixed. There is no need to add another city for a long time. (If the city list changes, recompiling is not a problem)
For example a Contact object have another property named FooBar which is going to be hold 1000 different string values and these values is going to be selected from a combo box for that property. And this set can be grown if users want. How do you load the combo box with these values? (If the string list statically written to combo box object, recompiling is a problem)
I have different solutions as below
All string values statically written to combo box in code or designer
Get the values from a resource file
Write those values to an XML file (Actually same as above, but no need to recompile)
Make a City object and get the values into a list from CITY table with NHibernate
Make a class named StringHolder which has a Type and Value property. All string values(including City and FooBar) would be written in just one table named STRINGHOLDER. And get those values with a key like "CITY" or "FOOBAR" with NHibernate.
Which one would you choose? Or could you suggest me another one?
Thanks all
I would vote for solution #4. That's the way I have always done it in similar situations. It just seems like a cleaner solution.
If the locations are actually going to be used for anything, get them into the database. If the data "isn't really used", but cities lookup is provided to make the user interface better, then the XML file option is not a bad way to go either.
By used, I mean stuff like list all emplyees in New York and stuff like that. If it's "dead data", just to be displayed, go for the solutions that will require the least amount of work and least risk - which might be the file option.
How do you feel of using List<string> for a list of City? Load this list of strings in your DAL or BL and then pass it on to UI.
Same solution should be good for FooBar values too.
In case you have IDs associated with City or FooBar, say NY and its numeric ID in DB is 1, then you can use KeyValuePair<TKey, TValue>. With generics you can dictate what data goes in this KeyValuePair. City name or FooBar's string value can be key and numeric ID can be value.
Just 2 cents.
Related
I have an ADO.NET DataSet that is persisted as XML. I need to add to it a list of cities and allow the user to select which city they're in. The selection has to be stored in the XML file along with the rest of the data.
This seems like a perfect use for DataSet.ExtendedProperties. However, it turns out that, in order for the extended properties to get written to the XML, I need to use XmlWriteMode.WriteSchema and XmlReadMode.ReadSchema, which adds the entire schema of the DataSet to the XML file just so it can add a single attribute, msprop:CityID.
My DataSet is strongly typed and its schema is hard-coded by the designer, so I really don't need to store the schema in the XML, which can lead to run-time errors.
So my question is, what's the best way to add the selected city to the DataSet itself. For example, using another table called SelectedCity, or using a Boolean column in the City table called IsSelected.
The SelectedCity table will always need to contain exactly one row, and the IsSelected column will need to contain true in exactly one row and false in all the others, and I don't know how to enforce such constraints in ADO.NET.
This seems like a fairly common scenario. What's the recommended way to code it?
If the relation is 1 to 1 put the field in the parent, but if a user can have various 1 to N put in another table. Sorry for my english.
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?
Please note that the database design I have now is fully in sandbox mode. Nothing is finalized. Everything (again this is in sandbox mode) is in one single table. Also, I'm in now way looking for coding help. I'm looking for the right theoretical/logical approach to this puzzle so I can go in and play with the coding myself. I learn better that way. If I need coding help, I'll come back here for further assistance.
I'm in the process of creating the first of a few CheckBoxList for a manually created form submittal. I've been looking over multiple ways to not only create said CheckBoxList but to enter it into the database. However, the challenge I'm facing (mainly because I haven't encountered this scenario before and I'd like to learn this) is that I not only need to worry about entering the items correctly in the database but I will eventually need to produce a report or make a printable form from these entries.
Let's say I have an order form for a specific type of Barbeque grill and I will need to send this form out to distriution centers across the nation. The distribution centers will need to pull said barbecues if they are highlighted on the form.
Here's what the CheckBoxList for the distibution centers will look like:
All
Dallas
Miami
Los Angeles
Seattle
New York
Chicago
Phoenix
Montreal
If the specific city (or all the cities) are checked, then the distribution center will pull the barbecue grill for shipment.
The added part is that I want to:
be able to create a grid view from this database for reporting to note which distribution center got orders for barbecues and
be able to create reports to tell what distribution center sent out barbecue orders in a given month (among other reporting).
Here's what I'm playing around with right now.
In my aspx page I have a checkboxlist programmed with all the distribution centers entered as a listitem as well as an option for 'ALL' (of the distribution centers).
I also created a dedicated column in this table that holds all the information in the listitem and programmed a sqldataconnection to this table to play with the programmability of leveraging the database for this purpose.
When it comes to writing the selections to the database, I originally created a column for each destination city including the 'All' option. I was toying around with just putting the selections into one single column but with some of the information I've been reading today about Database Normalization, the former options seems to be a better one than the latter. Is this correct practice for situations such as this especially if I need to think about reporting? Do I put the CheckBoxList data in one cell in a specific column? Do I create seprate columns for each distribution center? Am I even on the right track here?
Depending on the amount of cities that you want to store, I've used bitwise operators to store small amounts of data. Effectively, it would store it in the table like this:
CityID Location
2 Dallas
4 Miami
8 New York
16 Chicago
32 Montreal
and keep going in base 2 for additional cities.
When your user selects multiple cities for the order, the value that gets inserted into the database for cities is a bitwise OR calculation. So if they select Dallas, New York, and Chicago, you would be doing the following:
2 OR 8 OR 16
Which would equal 26
Now, you can use bitwise AND on the resulting value. So if checking for Miami the following is the evaluation:
26 AND 4 = 0
which indicates that Miami was not selected. Any value that was selected in the evaluation, it would return its ID like this:
26 AND 8 = 8
Again, I've only used this for small subsets of data, and to make the data storage as compact as possible. Computationally, it may be a trifle more expensive that some other methods, but I'm not 100% certain.
Note: This might not be the best approaches but I have seen them used.
1) Having one column of comma-delimited string
This should work well if the options don't have IDs in the database (having a separate referenced table)
You will need to loop through the checkbox list, obtained the selected options and concatenate them with String.Join()
You will need to split the string upon receiving it from the db and use it to check the checkboxes if there text is found in the resulting array
Problem: You might need a split function in the DB that converts the comma-separated string into rows. There split function implementation on the web/stackoverflow
2) You can have a separate table for the locations e.g. xxxxtable_location where the FK to the main table is referenced. This will be a one-many table
ParentID, Location
1 Dallas
2 Miami
2 New York
2 Chicago
3 Miami
I have this problem and I don't know what is the best solution for it.
I have table called Employees and there is column called LastWork, this column should only have custom values I choose for example:
value 1
value 2
and I want the user to select the value from ComboBox control so I have 2 ideas for it but I don't know what is the best for it.
A - add these value to Combobox as string in Items property and store them as string in DB.
B - create separate table in my db called for example 'LastWork' with 2 columns 'LastWorkID', 'LastWorkName' and insert my values in it, and then I can add binding source control and I can use data bound items to store the id as integer in my main table and show the LastWorkName for users.
I prefer to use the B method because in some forms I have DataGridView control with edit permission, and I want to display Combobox in it instead of Textbox to select from these custom values.
I hope you understood my questions.
Normally data normalization is a good thing, so I too would go with your option B.
By having a separate table and a foreign key relationship to it, you can enforce data integrity; easily get a list of all available (not just all selected) options; have a single place in which to change the text of an option (what if someone decides to call it "value one" instead of "value 1", for example?); and so on and so forth.
These might not be huge benefits in a small application and with only two possible options, but we all know that applications very often tend to grow in scope over time.
In a normalized database, your "option B" is usually the way to go because it eliminates duplicate data. It will potentially introduce an additional join into your queries when you need the name (and not just the ID), but it also allows you to rename lookup names easily without altering their underlying IDs.
For performance reasons, it's often a good idea to cache lookup values such as you describe in the business tier so that your lookup table is not hit over and over again (such as when building many rows of a grid).
I would always save them in the db. If you have to localize your app, this helps alot. Additonally, it let you to apply the referential integrity checks of the database.
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 ...