Connecting a gridview to multiple tables linqdatasource - asp.net

I'm just playing with some linq and asp.net - absolute beginner so I'm not even sure exactly how to ask my question.
Anyway, I have a MSSQL database with asp membership info in it. For various reasons (mainly to store profile info in clear columns instead of all in one) I'm using a custom profile provider so my profile information is spread across a few tables in my database.
I have the normal aspnet_membership and aspnet_profle, but then I also have a tblUserProfile table, in which I store a bunch of user profile information like first name, phone number etc. The tblUserProfile also has a companyID in it, referring to a seperate table with a list of companies in it.
All tables have a GUID UserId as their key.
I created a datamodel diagram that contains all the tables I'm using and it shows the keys linking up etc properly.
So now I have a gridview that uses a LinqDataSource that is connected to the aspnet_membership table. This bit so far works well, I'm able to display all the info in the aspnet_membership table. I also figured out how to show the company a user is in like this:
<asp:TemplateField HeaderText="Company" SortExpression="tblUserProfile.Company.CompanyName">
<ItemTemplate>
<%#Eval("tblUserProfile.Company.CompanyName") %>
</ItemTemplate>
What I can't figure out is how to make changes to this save to the database. If I change direct fields in aspnet_membership table, they update properly.
I created a dropdown showing all available companies, you can select the company to change directly in the grid, but when I try to update it reverts back to the original value.
<asp:TemplateField HeaderText="Company" SortExpression="tblUserProfile.Company.CompanyName">
<ItemTemplate>
<%#Eval("tblUserProfile.Company.CompanyName") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="CompanyDropDownList"
DataSourceID="CompanyDataSource"
DataValueField="Id"
DataTextField="CompanyName"
SelectedValue='<%#Bind("tblUserProfile.CompanyID") %>'
runat="server">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
I'm not sure if it's because my datasource is connecting to one table (aspnet_membership) but the value I'm trying to change is in tblUserProfile. It seems that I can retrieve/display values from the other tables connected via foreign keys, but can I also update values in those tables?
Sorry for a long winded question, but I'm pretty new to this so aren't sure exactly where the problems are otherwise I'd be more specific.
Thanks for any pointers

It sounds like you are trying to use the automatic updating provided by the LinqDataSource but as you point out, that doesn't work properly with joined data. That is a limitation of the automatic updating. You can however subscribe to one of the OnUpdating events and write some code to handle the additional updating. How exactly that should be written depends on the names of your key values, etc. but there should be some information about it on this site and elsewhere.

You can create a custom databound control to edit the sub objects
public class CompositeBoundField : BoundField
{
protected override object GetValue(Control controlContainer)
{
object item = DataBinder.GetDataItem(controlContainer);
return DataBinder.Eval(item, this.DataField);
}
}
And then use this in a page like so:
<cc:CompositeBoundField DataField="aspnet_Membership.Email" HeaderText="Email"/>
Then add this to the web.config:
<pages>
<controls>
<add assembly="App_Code" namespace="CustomControls" tagPrefix="cc"/>
</controls>
Let me know if this helps by giving me an up-check. It is possible to create other bound fields for checkbox or other types. This may have been the original author/source for this method:
http://iridescence.no/post/FixingBoundFieldSupportforCompositeObjects.aspx

Related

How to save list of team members in asp.net to sql server database table?

I am designing a Follow up report form in asp.net for employees to enter data in it and save the data to the database table. The form looks as below,
I know to save data until team members as they are either one selection or textbox value but I don’t know what to do about Team members. There may be up to 16 members in a team. How shall I save it in the database? Shall I create 16 different varchar fields like teammember1, teammember2, … teammember16 but that will be too much. Which asp.net control to use for this team members values? Shall I use separate textboxes for each member in team? I am really confused what to do about team members in the above form. Could anyone help me and let me know how to do it correctly.
First Question : how we can save team member values to database
You can use different ways.
one way you can save this all values in a single field as comma
seperated.The time of retriving you can split it .
Another way : Use a separate table and store one value per row, with a
foreign key pointing back to your table.
Note : The first method is a bad practice i prefer the second one
Second Question : Which asp control will be suitable here :
I think it is better to use Textbox here .
Note : Never display 16 text boxes at first time. just display 1 text box and after finishing the first textbox value it will dynamically create and show another textbox and so on.Untill the limit reaches.
Or you can use a jquery popup for getting the value of team
players. I think it will look smarter
"I am really confused what to do about team members in the above form."
You can do the following
For Webform:
Use a gridview control. Add textbox control in one of the template fields. You can add edit and delete template fields also in case you need to modify the data.
<asp:GridView ID="gvMembers" runat="server" AutoGenerateColumns="False" ForeColor="#333333"
ShowFooter="True" Width="212px" OnRowDeleting="gvMembers_RowDeleting">
<Columns>
<asp:TemplateField HeaderText="Team Member">
<ItemTemplate>
<asp:TextBox ID="txtMember" runat="server"></asp:TextBox>
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="btnAddMore" runat="server" Text="Add More" onclick="btnAddMore_Click"/>
</FooterTemplate>
</asp:TemplateField>
<asp:ButtonField HeaderText="Delete" Text="Delete" />
</Columns>
<HeaderStyle BackColor="#102040" Font-Bold="True" ForeColor="White" />
</asp:GridView>
You can find code for how you can make a gridview dynamic on the net.
For rest you can use the usual controls as shown in the image posted by you.
For Database
Create two database table.
One for the followup report (which will not contain team members)
create table follow_up_performance_report
(
report_id int primary key identity,
report_type nvarchar (20),
section nvarchar(30),
leader nvarchar(30),
head_leader nvarchar(30),
time_to nvarchar(50)
)
Next one for Team Members only.
create table report_team_members
(
report_member_id int primary key identity,
report_id int constraint fk_rep_id foreign key references follow_up_performance_report(report_id),
team_member nvarchar(30)
)
When you save webform, first insert it to follow_up_performance_report and create a method to call table's last report_id and then insert the rest (team members) into table report_team_members.
Hope this works for you.

How can I increase the performance of this FormView / SqlDataSource

I have a simple asp FormView on my page, it's working fine and everything, but I noticed the page is somewhat slow to load up (2-3 seconds), when there's really no reason for it, it's such a simple page.
The problem is that the FormView is using a SqlDataSource, which is using a 'heavy' select statement, basically grabbing all the fields and all rows of a profile table (name, address, phone, etc.). I'm assuming the FormView needs to get all the records so the Paging works correctly, but is there a way to code it or an attribute I can use so it doesn't grab every row and column but just all the columns of the current NameId?
asp:
<asp:FormView ... DataSourceId="sdsNames" AllowPaging="True" DataKeyNames="NameId">
<EditItemTemplate>....</EditItemTemplate>
<InsertItemTemplate>...</InsertItemTemplate>
<ItemTemplate>
<asp:Label Text='<%# Eval("Name") %>'.../>
...
</ItemTemplate>
</asp:FormView>
<SqlDataSource ID="sdsNames" ... SelectCommand="SELECT * from tblNames">
I tried changing the SelectCommand to
SELECT * from tblNames where NameId=1
since the initial page should show the first entry. But then I lose the pagination, basically no way to view the next record.
What the Page looks like:
There is not a lot you can do to improve performance here. You're correct, the SqlDataSource does slow things down because it retrieves all of the rows from your table.
There are a couple of different approaches that come to my mind:
Remove fields from your query.
This is the simplest solution, though it might not apply to your situation. If there are fields you don't need to display / modify, remove them. So, rather than SELECT * FROM..., you have SELECT LName, FName, Mname FROM...
You're still getting every row, but at least there is less data in each row.
You could switch to the ObjectDataSource control.
I haven't used this control much, but MSDN says that it performs a little better, because it doesn't always have to retrieve every row:
Some data sources, such as the ObjectDataSource control, offer more
advanced paging capabilities. In these cases the FormView control
takes advantage of the data source's more advanced capabilities to
gain better performance and flexibility while paging. The number of
rows requested may vary depending on whether the data source supports
retrieving the total row count.
You could move away from the datasource controls.
This probably involves more complexity than what you're looking for, but it is the most flexible approach. You can retrieve just the columns and rows you want. You can create a PagerTemplate, and set the values when the FormView is databound. You would have to handle the PageIndexChanging and PageIndexChanged events to change the paging values yourself.

Records from table not showing and not edible in AxGridView

Lets say that I want to show records from a table into an AxGridView and make that AxGrivView being able to create, edit and delete a record, are there any good tutorial on how to accomplish that?
EDIT
I'll try and explain what I've done so:
I've this dataset:
with these properties for eg. TrvExpParm_cars:
My user control contains this code:
<dynamics:AxColumn ID="TopRowRight" runat="server">
<dynamics:AxMultiSection ID="AxMultiSection1" runat="server">
<dynamics:AxSection ID="AxSection1" runat="server" Caption="Mine biler" Expanded="true">
<dynamics:AxDataSource ID="dsEPTrvExpParm_cars" runat="server" DataSetName="EPTrvExpParm" ProviderView="TrvExpParm"> </dynamics:AxDataSource>
<dynamics:AxGridView ID="AxGridView_cars" runat="server"
AllowDelete="True" AllowEdit="True" AllowPaging="False" BodyHeight=""
DataKeyNames="RecId" DataMember="TrvExpParm_cars"
DataSetCachingKey="xxxxxxxxxxxxxxxxxxx"
DataSourceID="dsEPTrvExpParm_cars" EnableModelValidation="True">
<Columns>
<dynamics:AxBoundField DataField="Name" DataSet="EPTrvExpParm"
DataSetView="TrvExpParm_cars" SortExpression="Name">
</dynamics:AxBoundField>
<dynamics:AxBoundField DataField="LicensePlate" DataSet="EPTrvExpParm"
DataSetView="TrvExpParm_cars" SortExpression="LicensePlate">
</dynamics:AxBoundField>
</Columns>
</dynamics:AxGridView>
</dynamics:AxSection>
</dynamics:AxMultiSection>
</dynamics:AxColumn>
What I get is an empty grid:
The table EPTrvExpParm_cars contains two fields with 2 records:
I really don't know why I can't see the data from the table. Are there some properties that I need to set or do I need som custom code? According to the Dynamics AX 2012 Enterprise Portal Cookbook, custom code shouldn't be needed, but again it's just a "cookbook"
UPDATE
The relation between TrvExpParm and TrvExpParm_cars is this:
What is the relation between your TrvExpParm and TrvExpParm_cars?
The way your datasource is defined the TrvExpParm is the data provider (providerview) so it will look for a TrvExpParm record (the first) and will try to show the linked TrvExpParm_cars records because in your gridview you choose TrvExpParm_cars as DataSetView.
The following whitepaper should help you do that: Microsoft Dynamics AX 2012 White Paper: Enterprise Portal Development Cookbook
A quote from the document:
AxGridView also includes built-in data modification capabilities. By using AxGridView with the declarative
AxDataSource, you can easily configure and modify data without writing code. [...] AllowInsert, AllowEdit, and AllowDelete properties control the create, read, update, and delete operations on the grid.

Trouble with user selection of records in ASP.NET GridView

Goal
What I need is to display a SQL DataTable to the user on a webpage through ASP.NET and allow them to select a number of rows very quickly and easily, and then hit any of a number of different buttons to signify different operations. The selected rows are to be sent off to be processed (generally sent to a webservice or similar through codebehind). This is a somewhat generic solution, as I will be using this same setup in many places - thus the data, and the available operations will be different.
The goal is to be able to know basically nothing about the data - that is for the user to understand. If this concept is already impossible (though I believe it is not), please let me know.
Pulling from T-SQL (SQL Server 2008 R2 or later).
Using ASP.NET to make aspx webpage. Codebehind is done in VB.NET, in both cases we're using 4.0
I'm fluent in C# and VC++, so if you can't easily translate your code, don't worry about that.
The problem
My problem has been creating a row selection process for the user which persists while sorting or paging the table, is quick for the user and relatively quick in response time, and which is reflected in the GridView's bound data (as this allows me to use a filter on a DataView to produce a DataTable for passing). If there's another way to know the selected rows then I'm all game so long as it is persistant and quick for the user.
I'm not debugging and I'm not having syntax issues (I do not believe) - I don't know how to proceed.
I don't necessarily need code as a solution - I need to understand if my metaphor is either bad practice, or simply uncommon and thus not well supported. In either case, what is an appropriate way to proceed? If nothing else, where do I look for a solution besides endless API and Tutorials?
My original plan
I wanted to use asp:GridView for binding the DataTable pulled from TSQL since I can auto-generate columns. This allows me to display data without needing to know what it is. I planned to add a specific boolean Column (left most) for storing the User's row selection. Then I can simply run a filter on the DataTable to produce a DataView, get the resulting DataTable from that DataView, and pass it down the chain.
All the columns except our specific selection one would be Read-Only. The user isn't editing data - their selecting records and view their selection side-by-side with the viewable relevant data.
Of note, I planned to check for name collision so our added Column doesn't collide with any existing Column in the DataTable - I'd rename it as needed using 'Select' followed by an integer produced by looping through, comparing my name to other columns, incrementing as needed.
I presumed that once I set this up, it would just handle itself: the user could click the resulting checkbox column cell's and it would change the data on the fly. The point of saving the selection was their selection persisted through sorting and paging for convenience (I save the GridView's DataSource and re-bind when necessary). It didn't really matter if the user refreshed the page and completely and lost their checkboxes - they would need to review any changes/new data, and they wouldn't need more then a brief moment to check off whatever they wanted.
This did not happen.
I found that AutoGenerateColumns does not produce checkboxes for boolean DataColumns. It produces text, so I end up with the word 'True' or 'False'.
I began looking for a way to get check boxes in the cells for a boolean DataColumn. I found that for the added boolean column, I could bind an asp:CheckBoxField to it using the attribute DataField. Of course, I have to figure out how to point it at a variable DataField...
<Columns>
<asp:CheckBoxField DataField="Select" HeaderText="Select"
ReadOnly="False" SortExpression="Select">
<ItemStyle HorizontalAlign="Center" />
</asp:CheckBoxField>
</Columns>
However, because a GridView is designed for Row-By-Row editing, all the resulting CheckBoxes are disabled and cannot be checked. This is because their containing row is not in Edit Mdoe. I do not want to enable Row-By-Row editing using a button or similar metaphor as the user often needs to check off several rows. More clicks is bad, and annoying. They should be focused soley on their data and making their selection, not worrying about remembering to enter and end edit mode. Also, the metaphor seems poorly placed here since the checkboxes are the -ONLY- editable data - and are not part of the represented data.
I could, of course, make a new class which inherits from GridView, overload the method which generates columns to produce checkboxes instead of text fields - but I felt there had to be a more straightforward path. Maybe this is the way to go? But maybe it would have the same editing issue as above - I'm not sure.
So, next I tried looking at using an asp:TemplateField as a column in my GridView. This TemplateField contains an asp:CheckBox who's Checked state is based on the underlying bound data value. The issue here is trying to make changing the check-state update that bound value. I would need some way of looking up a GridView value I could then use to find the same row in the DataTable. I've seen great examples using a Primary Key. While I could assume everyone keeps a Primary Key for any possible table, this might not be the case! I could further add a Primary Key myself, but now it looks like I would be adding and removing two columns before I pass a DataTable off to a WebService instead of just one. Again, I also would need to be able to assign a Column name which is dynamic to avoid collision.
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox runat="server" ID="CheckBox"
Checked="<%# DataBinder.Eval(Container.DataItem, "Select") %>"
AutoPostBack="true" OnCheckedChanged="SelectCheckBox_CheckChanged" />
</ItemTemplate>
</asp:TemplateField>
I stopped myself - This path is also fairly indirect. Surely there is a much cleaner, simpler way to do this. Is it uncommon for someone to display Read-Only data where records are selected to be submitted, in one fashion or another, for processing/updating/alteration?
Is my choice of GridView poor? I haven't yet found another good way to represent Table data.

Turning information from a datasource into links

I have a web application where I am getting data from an oracle database in a gridview.
Can anyone tell me how to turn this data into links to other pages on my web application?
For example, if I am getting data about a list of objects that have their own ID, I want to be able to click the ID and go to a page with information on only that object
This is all the code for my gridview, in SystemGrid_Sorting, I get all the info from the databse, so I can't actually define the properties of my columns.
Thanks in advance
asp:GridView ID="SystemGrid" runat="server" AllowSorting="True" Width="232px" OnSorting="SystemGrid_Sorting" >
This is very easy:
<asp:HyperLinkField DataNavigateUrlFields="ID"
DataNavigateUrlFormatString="DetailPage.aspx?id={0}"
DataTextField="CategoryName" NavigateUrl="DetailPage.aspx" />
Now just set up DetailPage.aspx to call into the database using the ID in the querystring and display whatever you like.
Essentially, given an ID 1234 you need to turn it into an HTML link like:
1234
I don't know whether your gridview tool has a built-in method for constructing such links for you?

Resources