Linq to SQL Design question - asp.net

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".

Related

How to assign dynamic data source to GridView using Entity Framework?

I have an Stored Procedure which may return some unpredictable rows and columns, based on some business logic written in my SP. That is for sure that it will return only one set of Result Set data from this SP.
Whatever the result my SP returns, it should be reflected into my GridView. Due to some framework restrictions, I can not use ADO.Net DataSets/DataTables.
I am using Entity Framework 4.0 for my project and I want some solution to bind my GridView with dynamic nature of DataSource returned by my Stored procedure.
I think, this is very common problem which many developer has encountered in such type of situation.
Is there anyone who have found some work around to achieve the goal within the boundary line of Entity Framework?
Note: Keep in mind that, I don't want to use ADO.net DataSet or DataTable.
I think you are fetching data from proc and stored in List like that.
List<HRDocumentCheckList> searchJoiningDoc = GetJoiningDocumentForEdit(ddlCategory.SelectedValue.ToInt32(), false).ToList();
gvJoiningDocumentTemplate.DataSource = searchJoiningDoc;
gvJoiningDocumentTemplate.DataBind();
Just bind the gridview and set the autogenrated column is false
Hope it will helps you

ASP.NET Custom Paging

How to keep custom paging for dynamic result sets ? (i.e) based on 10 Dropdowns selection my stored procedure will Dynamically generates resultset,but it populates million records.
Row statically know Record count,cusom paging is efficient,but how to achieve it for dynamically grown result set?
Problem
I have to bind generic List to GridView,Columns are fixed,but the number of rows retuened are unknown,but without custom paging my GridView took 30 minutes to populate the result.
If possible, you should use LINQ, as the extensible operations make for easy paging.
Essentially, you would specify an ObjectDataSource or LinqDataSource for your GridView.
You would then have an IQueryable<T> method which accepts a starting position and number of rows to retrieve.
Then you make use of Skip() and Take() to achieve simple paging.
Here's a very good article on doing that.
Remember that Skip() and Take() are methods exposed to any class which implements IEnumerable. So even though the above article uses LINQ-SQL for their data repository, as long as your own DAL exposes a collection of type IEnumerable, you can use the Skip and Take pattern.
Hope that helps.
An easy way to do this server side would be to use LINQ. Took at the .Take() method.

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.

ASP.Net Entity Framework Model

Is it possible to add properties to my model that dont exist in the database?
For example I have a calendar table, I want to retireve this data in my MVC controller then work out time left until each entry starts and return this to the view. So I would like another property in my calendar model to hold time left which is a value that I will generate outside of the database.
I've tried just adding the property but when I do that I get errors because the property is not mapped to anything.
Is this even possible?
Thanks
You should be able to add the property to the Model but you will not be able to query it with LINQ. LINQ will ultimately build and expression which it will want to run against the database using SQL. Its at that point that your LINQ will fail to find a mapping from your property to a field somewhere.
If your query returns an IEnumerable of the actual type on which you have created the property your view may be able to access it. I can't remember if EF insists on mapping in that case, it may do.
You might find that you can create subsequent LINQ query that uses LINQ-to-objects if you want to provide some other composite type to your view.
It's a non-persistent property or transient. I don't know Entity Framwork well but with a quick google search you should find the answer.
BTW you can find a lot of tips here :
http://weblogs.asp.net/zeeshanhirani/archive/2008/12/18/my-christmas-present-to-the-entity-framework-community.aspx
After making a quick search myself and a test in VS2008 I don't see a way to exclude a property from the mapping. Maybe it requires you to edit manually the mapping file ? :(

Can linq2sql do this without a lot of custom code?

Just dipping my toes into Linq2sql project after years of rolling my own SQL Server DB access routines.
Before I spend too much time figuring out how to make linq2sql behave like my custom code used to, I want to check to make sure that it isn't already "built" in behavior that I can just use by setting up the relationships right in the designer...
Very simple example:
I have two tables: Person and Notes, with a 1 to many relationship (1 Person, many notes), linked by Person.ID->Note.PersonID.
I have a stored procedure (all data access is done via SP's and I plan on continuing that) which makes the Link2SQL a bit more work for me.
sp_PersonGet(#ID int) which returns the person record and sp_PersonNotesGet(#PersonID) which returns a set of related notes for this person.
So far so good, I have an object:
Dim myPerson As Person = db.PersonGet(pnID).Single
and I can access my fields: myPerson.Name, myPerson.Phone etc.
and I can also do a
Dim myNotes As Notes = db.PersonNotesGet(pnID)
to get a set of notes and I can iterate thru this list like:
For Each N As Note In myNotes
( do something)
Next
This all works fine...BUT....What I would prefer is that if I call:
myPerson = db.PersonGet(pnID)
that I also end up with a myPerson.Notes collection that I can iterate thru.
For Each N As Note In myPerson.Notes
( do something)
Next
Basically, Linq2SQl would need to call 2 stored procedures each time a Person record is created...
Is this doable "out of the box", or is this something I need to code around for myself?
This is normally what we would call child collections and they can be eager loaded or lazy loaded. Read these:
http://davidhayden.com/blog/dave/archive/2009/01/08/QuickExamplesLINQToSQLPerformanceTuningPerformanceProfilingORMapper.aspx
http://www.thinqlinq.com/default/Fetching-child-records-using-Stored-Procedures-with-LINQ-to-SQL.aspx
It uses partial classes. You can add your own "Notes" property to your Person class and initialize it in it's GETter function. This would be better than populating the notes every time you load a person record.
I believe that you can do this more or less out of the box, although I haven't tried it -- I don't use stored procedures with LINQ. What you would need to do is change the Insert/Delete/Update methods from using the runtime to use your stored procedures. Then you'd create an Association between your two entity tables which would create an EntitySet of Notes on the Person class and a EntityRef of Person on the Notes class. You can set this up to load automatically or using lazy loading.
The only tricky bit, as far as I can see, is the change from using the runtime generated methods to using your stored procedures. I believe that you have to add them into the data context as methods (by dropping it on your table from the server explorer in the designer) before it is available to use instead.

Resources