I've never looked much into all what .NET offers for user input validation because to start with I dislike the way they will typically not let you unfocus a control unless you enter the right data (I believe the DataGridView does this).
On the other hand, I found that I often need to validate what I'll describe below and I wonder if sticking to .NET standards here will make it any easier.
I'll typically have a dialog box that among other controls will have two combo boxes: one to select a data table among existing tables, and one to select a column among the columns in the currently selected table. This is easy enough so far, but since this is a dialog, I need to show the values that were selected the last time the dialog was shown if they still exist in the database, or otherwise select some other column if the table still exists, or select another table and column if there is any table and warn the user that his selection has changed, or if there are no tables simply show a message and close the dialog.
Of course this is not the only case. Sometimes it will be a bit more complex and every time I will try to figure out again what's the best way to handle it. I wonder if there is already a pattern, particularly one that .NET offers I can apply to the case I describe above? If so, I'm sure I'll figure out how to apply it to other cases.
The answer will depend quite a bit on your implementation specifics.
However, what we finally settled on for this was to pass the existing display and value values to the method that retrieves the data.
Once the data is retrieved, we check to see if the missing data is present in the retrieved data and, if it is, we add a record to store the display and value values to the collection of data that is returned.
Implementing this functionality at the point of data retrieval allows us to support the same functionality in any client (asp.net, silverlight, etc).
We do go back and forth occasionally on whether it is appropriate to add the logic to the business object, but there are enough exceptions (i.e. web services, simple collections, etc) that we always end up back at the above design.
Related
I Want to let user decide which column or field he want's to add in Objectand depending on what data type he has chosen to create that field, user should able to make CRUD operation on that object with data type chosen by him to create that custom field. Is it possible or not, If yes what are the optimum ways to create it? (All this operations to be made in browser and not from code)
You cannot "dynamically" add a column to a table per row. If the user could add a column, then that column would be added to the table in general, and every row in that table would have it. Even if this was possible, it would require granting your application admin rights on your database, which is a huge security faux pas. The database user exposed to the web should have only the most minimal privileges necessary: usually just INSERT, UPDATE, SELECT, and DELETE, and sometimes not even all of those. Anything more puts you at huge risk of SQL injection attacks and similar by malicious users. This is database 101 stuff, so it may behoove you to step back and learn more about the platform you're developing on before proceeding.
It's sounds like you're basically just want something similar to a "settings" table. The way these things normally work is store the name of the "setting" and a value for that as a string. You might also store a type value, also as a string. Then, after you retrieve the setting you can coerce the value into the proper type you need it as. That's really the best you can do with "dynamic" things, since a relational database is very much static. It needs to know the data and the types of that data it's going to handle in advance.
I am writing a GUI that will be integrated with SAP Business One. I'm having a difficult time determine how to load, edit, and save the data in the best way possible (reliable, fast, easy).
I have two tables which are called Structures and StructureRows (not great names). A structure can contain other structures, generics, and specifics. The structures rows hold all of these items and have a type associated with them. The generics are placeholders for specifics and the specifics are an actual item in inventory.
A job will contain job metadata as well as n structures. On the screen where you edit the job, you can add structures and delete structures as well as edit the rows underneath them. For example, if you added Structure 1 to Job 1 and Structure 1 contains Generic 1, the user would be able to swap Generic 1 for a Specific.
I understand how to store the data, but I don't know what the best method to load and save the data is...
I see a few different options:
When someone adds a structure to a job, load the structure, and then recursively load any structures beneath it (the generics and specifics will already be loaded). I would put this all into an Object Model such as List and each Structure object would have List and List. When I save the changes back to the database, I would have to manually loop through the data and persist the changes.
Somehow load the data into a view in SQL and then group and order the datatable/dataset on the client side. Bind the data to a GridView so changes are automatically reflected in the dataset. When you go to save, SQL / ADO.NET could handle this automatically? This seems like the ideal solution, but I don't know how to actually implement it...
The part that throws me off is being able to add a structure to a structure. If it wasn't for this, I would select the Specifics and Generics from the StructureRows table, and group them in the GUI based on the Structure they belong to. I would have them in a DataTable and bind that to the GridView so any changes were persisted automatically to the DataTable and then I could turn around and push them to SQL very easily...
Is loading and saving the data manually via an object model the only option I have? If not, how would you do it? I'm not sure if I'm just making it more complicated then it needs to be or if this is actually difficult to do with C#, ADO.NET and MS SQL.
The HierarchyID datatype was introduced in SQLServer 2008 to handle this kind of thing. Haven't done it myself, but here's a place to start that gives a fair example of how to use it.
That being said, if you aren't wedded to your current tables, and don't need to query out the individual elements (in other words, you are always dealing the job as a whole), I'd be tempted to store the data for each job as XML. (If you were doing a web-based app, you could also go with JSON.) It preserves the hierarchy and there are many tools in .NET for working with XML. There's also a built-in TreeView class for winForms, and doubtless other third party controls available.
I tried my best to come up with an appropriate title, excuses if it doesn't make much sense. I hope to explain it better below. We have an application that is based on .Net framework and uses SQL as data storage. As with any application, this application need to support extensibility, for example to support additional data transformations & validations.
Example: Think of the application as a tool that provides a set of input tables the user can import data into using access or excel (there is UI & grids already) to allow data import. Once the data is imported the tool creates an intermediate model and performs some calculations on the input data and later throws the results in pre-defined format. The input table schema and intermediate model schema is fixed, no changes will happen. The extensibility is needed in the stage where the intermediate model is derived from the input data. Allow users to be able to change the way the data gets derived, eg instead of grouping by one field allow grouping by multiple fields etc.
To support this kind of flexibility, I see there are two basic approaches as I could see
Option 1: Create a business model that maps to the sql data model and expose the business model to the user to allow them to override transformations & create new transformations (e.g., using LINQ or plain C#)
Option 2: Expose the entire sql data model and allow users to embed raw SQL queries to perform the transformations & validations.
My personal preference is to use Option 1, since I am not a big fan of allowing users to play with underlying data tables directly. I prefer more controlled access. However, this approach requires the user to have programming language (C# or VB). On the other hand Option 2, may just need someone who has knowledge of SQL programming to create raw queries and directly plug them into the application. But, I think this is a bad approach.
The product management team is inclined to go with Option 2, as they feel it is more flexible and easy to implement from resource point of view.
So, I am trying to come up with pros and cons of both approach to better support my inclination for Option 1. Basically, inclination to do the work in programming language in C# or VB .net rather than just using plain SQL queries.
Kindly, share your thoughts and opinions.
Neither option is a good one.
End users are (theoretically) proficient in the business logic - they shouldn't need to be proficient in a programming language to do their job.
What you should do is create a framework for extending things using standard controls - combo boxes, text input, grids, etc. It's hard to give you specific advice without specifics of what kind of extensibility you're looking for, but I'll give you an example from my projects:
Our users need a way to add arbitrary tags to products, for filtering on our website. We created a data grid where they could type in the name of a type, specify whether it's a "True/False", integer, decimal, or a value off of a list, and then set the items for said list. Then, on each product, they are presented with the list of all the applicable types and they need to fill in values - the "True/False" produces a checkbox, the integer and decimal produce text fields which validate, and the list produces a combo box of all the options they specified. Whenever they want a new property, they can go add it themselves, but they don't need to think about how those properties work at all, because the website operates based on the type.
Ok, based on your example, I would suggest this:
Provide a form which lists every column of the data and has a combo box next to it to specify what action to take. The actions can be chosen from a list which contains things like:
Ignore data
Use data as-is
Format data
Look up value elsewhere
Perform calculation
Based on the user's choice in this dropdown, you would:
Not include the column in the output
Use the data as-is.
Provide a button to open a form where they can format the data (probably with a subset of the String.Format options) based on the type of the data. You'd show a key on the bottom to show what values are supported.
Provide a button to specify what "elsewhere" is. This is probably where extensibility will be most useful, so I'll address it again below
Provide a way to enter an appropriate calculation.
As for the "elsewhere" lookup, this would probably be mostly listings of values and strings to transform it with. Those values can be specified in a configuration section of the application, and stored in a table somewhere. You can create arbitrary groupings of them to represent various "lists" of options. Alternatively, you could list some existing data tables which you would want the users to reference, and let them specify a transformation (using the calculation screen) to convert their value to a lookup on the other table.
Is this making sense?
EDIT: Solution (kind of)
So, what I did had very little in common with what I originally wanted to do, but my application now works much faster (DataSets that took upward of 15 minutes to process now go through in 30-40 seconds tops). Here's roughly what I did:
- Read spreadsheet & populate DataTable/DataSet normally
- [HACK WARNING] Instead of using UpdateDataSet, I generate my own SQL queries, mostly by having a skeleton string for each type of update (e.g. String skeleton = "UPDATE ... SET ... WHERE ..."). I then consult the template database and replace the placeholder ... with the appropriate entries.
- [MORE HACK WARNING] The way I dealt with errors was by manually checking whether those errors will occur. So if I know I am about to do an insert, I'll run an error-checking command before the actual insert; what the error checker will do is construct a JOIN statement, checking whether any of the entries in the user's DataSet already exist in the database. Just by executing the JOIN command, I get back a DataSet with the results, so I know that if there is anything there, it's the errors. Then I can proceed to print them.
If anyone needs more details, I'll be happy to provide them. It's a fairly specific question, so I should probably keep this outline fairly high level.
Original Question
For (good) reasons outside of my control, I need to use the Database.UpdateDataSet() method from Microsoft's Enterprise Library. The way my project will work, I am letting the user make changes to the database (multiple database, multiple schemas, multiple tables, but always only one at a time) by uploading Excel spreadsheets to a web application. The spreadsheets follow a design/template specified by me (usually). I am a state where I read the spreadsheet, turn it into a DataTable/DataSet, and use (dynamically generated) prepared statements to make the appropriate changes to the database. Here's the problem:
Each spreadsheet only allows for one type of change (insert/update/delete). I want to make it so if the user uploads an insert spreadsheet, but several (let's say 10) of the entries are already in the database, I not only return with an error, but also tell them which entries (DataRows) violated the primary key constraint.
The idea solution would be get a DataSet with the list of errors back, but I don't see how I can do that. Perhaps there is a way to construct the prepared statements in such a way that if a DataRow is to be inserted (following the example from above), it proceeds normally; however if it attempts to update or delete, it skips it and adds it to an error collection of some sort?
Note that I am trying to avoid using stored procedures. Since the number of different templates will grow extremely quickly after deployment, it is important that I stay away from manually written code and close to database-driven model as much as possible.
I am having a little trouble deciding how to structure an application that I am building.
The application is required to parse through text-based files (one record per line) and load all of the information into memory. There are typically anywhere from 100,000 - 500,000 records. After that, the data must be displayed in the form of tables and very detailed graphs/charts for further analysis.
The user must have the ability to customize the view of this data. For example, there are many different "types" of log records (TypeA_Log, TypeB_Log, etc.) The user should have the ability to select/deselect these types, which will show/hide them from the display. There are several other types of filtering going on (filter by date, etc.)
--
Essentially what I have now is this:
I have a class structure that represents the various types of log records.
There is a Singleton pattern to hold all of the data (almost like a database in memory), which includes Lists<> of log record instances.
Then, I have a "filter" class which contains information about what the user would like to view. The "filter" gets passed into the Data-Singleton, and then returned a subset of the data. I am basically using C# lambda expressions to select data from a List<> of Log Records, similar to how you might pass in a SELECT statement to a SQL database.
--
This is working okay, but I have to think there is a better way of handling this. Right now, anytime the user makes even the smallest change (for example, selects/deselects one of the many types of log records, a new data set has to be retrieved from the Data-Singleton, and then all of the tables and charts have to be refreshed/rebinded/recomputed to reflect this change. All I really want to do, in most cases, is show/hide certain things.
I am using C# .NET 3.5.
You could build some sort of internal notification system, something also called event dispatcher.
Lets say have a record changed in one form, and instead of reloading other dependent forms, you fire the event that some record has changed (attach the record with some custom EventArgs), and let your dependent forms decide on event handling should they include this new record somewhere. You could update the changed data in the collections of the dependent forms.
However, this can create some concurrency problems (when you avoid rooundtrips to the database (text files in your case) )...