Split Table column in Dynamic data - asp.net

I am using an integer field in the DB to represent collection of booleans in order to save some space. the integer is used in my Business logic and transformed into collection Boolean attributes.
i'v now decided to add "Admin" section to the site using Dynamic data feature, and i am wondering whether there is an option to show the Booleans that represent that integer.
i know how to Hide a certain column (avoid scaffold) but i don't know how to add "virtual" column to the Dynamic control.
Maybe Sql View is the answer here? is there an easy way to bind the dynamic data into SQL view instead of the real table?

Have you tried creating a custom field template that would handle the logic of splitting/"joining" the boolean values into an integer?
MSDN:
http://msdn.microsoft.com/en-us/library/cc488523.aspx
Video:
http://www.asp.net/learn/3.5-SP1/video-291.aspx

Related

Allowing user to create new data types with custom properties

I am working on a web project where the user should be able to create custom types of merchandise containing any amount of properties of different types (numbers, text, etc). E.g: a box, which has name, price and physical dimensions, and a bottle, which has name, price, and volume.
What would be the best way to represent this in code and in the database?
My first idea was to create a basic template for a piece of merchandise, and dump all the custom data in a single field as stringified JSON. The downside is that this data couldn't be used for IQueryable search, filtering, sorting.
I can also think of creating a separate table, in which I'd store all the custom fields of all merchandise, and referencing them via relations. Wouldn't this, however, cause problems with scaling, as I will be essentially storing all custom properties everywhere in a single table.
Is in the best way to do it? There is no way to create new classes and database tables on the fly in .NET Core, of course, but what other options there are?
Thank you for your time,
I'm doing this in my current side project, and I've done it in the past as well. Basically, you will have a base Product table (or whatever you want to name it). Then you also have tables such as ProductAttributeType and ProductAttribute.
The base Product table would contain attributes common to all products, such as Name and Price.
ProductAttributeType
ProductAttributeTypeCode VARCHAR(10)
AttributeTypeName VARCHAR(50)
Where ProductAttributeTypeCode contains a short / abbreviated code for the attribute type (e.g. "BOOL"), and AttributeTypeName is a friendly name (e.g. "Boolean" or "Yes/No").
ProductAttribute
ProductId INT -- Foreign key to Product table
ProductAttributeTypeCode VARCHAR(10) -- Foreign key to ProductAttributeType table
AttributeName VARCHAR(100) -- The name of the product attribute (e.g. "Volume")
AttributeValue VARCHAR(MAX) -- Contains the actual value of the product attribute
Product has a one-to-many relationship with ProductAttribute.
This is the approach I've taken in the past, as well as in a current project, and it works pretty well. It appears to be a pretty common approach for solving this sort of problem. The only "downside" I can think of is that you need to make sure that the value in the ProductAttribute.AttributeValue column matches the appropriate type for ProductAttributeType(Code). If you design your code properly, and it's well thought out, it's really not so bad, in my opinion.

Why data binding does not remember the old values?

I have a classic ObjectDataSource and a ListView in my page. The List view just displays some data and when switched to edit template it allows the user to change the values. I want the user to edit just some values -- so I bind just these ones in the edit template.
The problem is that the other values suddenly turn to nulls or 0. I tried to bind all of the values at once and it works fine, but I cannot understand why the old/original values just disappear. Is there any way how to bind the old values?
Thanks for help.
The problem is, that only the data that is included into a round-trip to the server will be available in the postback. That includes all that that is bound to BoundFields, TemplateFields or if the Propertyname is included in the DataKey (or DataKeyNames, don't know right now).
The best approach to fix this, and to keep the overhead to a minimum is to add your primary key to the DataKeyNames collection. This allows you to have access to your custom object that contains an unique identifier and all properties that have just changes.
In your Update Method of the ODS (in your custom class) you now need to retrieve the old object by its unique identifier, manually assign the new values and saves your object back to the database

ASP .Net User Roles - ordering for a drop down

We are using the standard aspnet security features, we have need to set the order of the roles, purely for display purposes.
We could just have a sequence number onto the end of the aspnet_roles table, but that feels kinds of hacky to me. Also if in future versions of asp the security get changed we will be in trouble.
Is there a better way to do this that won't make me loose sleep each time a new version is pushed out?
If you don't want to change the existing schema, store the sequence data in another table and use a custom stored procedure to join the two together and return the values. Use the result of this stored procedure to populate the drop-down.
Don't forget to add a "special case" in the stored procedure to place roles that aren't contained in the second table at a "default" position in the returned set, rather than ignoring them, unless that's desired =)

Linq to SQL Design question

Often I need to combine data from multiple tables and display the result in a GridView control.
I can write a Linq query inline in the Page_load event, return an anonymous type that combines all the fields that I need, and databind the result to the GridView control.
Problem: I use 'helper methods' as described by Scott Guthrie on his blog. Such a helper method cannot return an anonymous type. The query would have to be inline for this approach.
I can write a database view that returns the data that I need, and write a helper method with a query against this (new and known) type that it returns.
Problem: I will need a lot of views in my database schema, and I will introduce a lot of redundant aspects of my data. I also lose some of the advantage of using Linq - removing all business logic from the database.
I would like to take an approach that lets me keep the Linq queries in helper methods, yet allows me to access all the attributes that I need on the grid in their respective databinding expressions. Can this be done?
I asked the wrong question, as I frequently do. What prompted me to look into anonymous types was an apparent limitation of the GridView - my inability to use a databinding expression in an <asp:BoundField> (the DataField parameter only accepts column names of the table that the Linq query pulls in).
Turns out that in a TemplateField it is possible to use Eval and access members of the Linq data item, and Linq takes care of the query for me.
In other words, I can keep the query in my helper method, have it return a primary database table type (e.g. Account), and I bind the Accounts to the GridView.
In the databinding expressions I can access data members of the Account objects that reside in other tables, without having to explicitly pull them in in the query. Perfect.
I don't know if there is a viable way to achieve this using anonymous types. But I have a suggestion that will work in WinForms, but I am not sure about ASP.NET.
What you need is a type with properties where neither the number of properties, nor the types and names of the properties are known at compile time. One way to create such a thing is ICustomTypeDescriptor.
You have to create a type implementing this interface with an private backing store of objects backing the properties returned by the query for one row from the query. Then you implement GetProperties() to return one PropertyDescriptor per column and PropertyDescriptor.GetValue() and PropertyDescriptor.SetValue() to access the backing array.
By implementing PropertyDescriptor.Name you will get the correct column name; this will probably require another backing store storing the property names. And there is a lot more to implement, but in the end your new type will behave almost like a normal type - and now the if - if the control you are binding to knows about and uses ICustomTypeDescriptor.
UPDATE
I just found an bit of text stating that ASP.NET data binding knows and uses ICustomTypeDescriptor.
Scott's earlier post in the series talks about shaping the result set before inserting into a grid:
Part 3 - Querying our Database
Scroll down to "Shaping our Query Results".

Make Gridview interact with something other than properties

We're planning to create a web application where users can build custom "forms," choosing which fields they would like, and how the data in those fields should be represented. Users can then fill out these forms in a DetailsView-like control, thereby creating "documents." The documents can be shown in a DetailsView, or certain fields of several of them can be shown in a GridView. At least, that's the idea.
The problem is that GridView and DetailsView seem to be specifically designed to access Properties on objects that come out of a DataSource. Since we want to have completely arbitrary forms, we can't restrict ourselves to building a class with Properties to represent each field. We have to be able to have any number of dynamically-specified fields on a form.
Is there any way to leverage the existing controls so we don't have to re-implement paging, sorting, and all the other things that GridViews are already set up to do, or will I just have to create my own GridView-like control from scratch?
Edit:
More specifically, the difficulty I am having is in getting inline editing to work on the GridView. For example, let's say that one of the "fields" that is added to a "form" is a calendar field, which should display a date as text in read-only mode, and display a calendar control in edit mode. When the "save" button is clicked, the date selected by the calendar control needs to be saved to the database as the new value for the given field of the given document (i.e. instance of the form). My initial idea was to create a special DataControlField class which, given a form field key, would know how to databind thusly:
FormDocument doc = DataBinder.GetDataItem(cell) as FormDocument;
FormFieldValue fieldValue = doc.FieldValues[FieldKey];
fieldValue.AddReadOnlyControls(cell);
... instead of:
Object dataObject = DataBinder.GetDataItem(cell);
cell.Text = DataBinder.GetPropertyValue(dataItem, FieldKey);
This would probably work for displaying the field values, but if the user tries to edit and save one of the FormDocuments I don't know how I would convince the GridView to do something like this:
doc.FieldValues[FieldKey] = newValue;
Currently, the API for DataControlField uses the ExtractValuesFromCell method to put the property name and value into an IOrderedDictionary. Those values are then applied to the given properties of the objects in the GridView's databound IEnumerable. The problem is, I can't work with properties of an object because in this case the object needs to have a completely arbitrary number of fields.
A GridView can be bound to any object that implements IEnumerable. The advantage of using one of the xDataSource controls is that it can implement paging and sorting for you without any additional code, but you certainly aren't tied to them.
If I understand your question correctly, you do not know the number of columns to display in the GridView until runtime. In that case, I would recommend building an array from your form data and binding the grid to that. You will have to implement paging and sorting yourself.
The DetailsView is not very customizable so you should take a look at the FormView. However, I think you are going to end up dynamically adding controls to whatever container you use.
What you need is totally dynamic GridView. I quess you would have to extend it with the controls ( functionalities ) in your description
Here's what I ended up doing:
I created a new data type that contained a Dictionary of answers, indexed by Field ID.
I created a new type of DataControlField with a FieldId property, which retrieves the proper answer value for that FieldId from the Dictionary mentioned above.
I added data type and data keys properties to this custom DataControlField and overrode the ExtractValuesFromCell method so that it could create a new instance of the answer class and add those values to a Dictionary, which was stored under the property name by which that dictionary would be found in the new data type mentioned in step 1.
I used my own GridView class, used the .NET Reflector to see how the normal GridView calls the ExtractValuesFromCell method, and then changed that so that it would pass the same Dictionary object in to each DataControlField. This way, each field could add to the same Dictionary, rather than replacing the Dictionary that the last one had added under the same property name.
I used a DataFieldGenerator to generate the one of my custom DataControlFields for every field associated with a given form, and I told the GridView to use that DataFieldGenerator to auto-generate its fields.
I set up my ObjectDataSource so that it would know how to save all the answer values from an object of the type mentioned in step 1.
It was tricky, but worthwhile.

Resources