- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
ObjectDataSource2 - Insert & Delete
Joined: 05-Jul-2006
ASP.Net 2.0 ORMapper = LLBLGen 2.0 Runtime Library = ORMSupportClasses.NET20.dll v2.0.0.60717 Template = Adapter General 2005 IDE = VS 2005
Questions about how the DataSource2 object works.
- Why can I not define Delete Parameters when I can define Insert, Update and Select Parameters?
- Why can I not call DataSource2.Insert, DataSource2.Update or DataSource2.Delete? I can call DataSource2.Select. My situtation: I have gridview bound to a DataSource2 object which is bound to an Entity Collection. It's a simple grid of 3 columns. In the footer of each column are the controls to add a new record to the table. I want to be able to click the "Add" button in the footer and call DataSource2.Insert(), but this method is not available. I tried setting the CommandName="Insert" for the "Add" button but that didn't work. This did work for the "Delete" button
Below is the code. Thank you for your assistance.
<cc1:MultisortIndicatorGridView ID="gvUserComputer" runat="server" AllowMultiColumnSorting="False"
AllowPaging="True" AutoGenerateColumns="False" DataKeyNames="Username,Computer"
DataSourceID="odsUserComputer" AllowSorting="True" ShowFooter="True">
<Columns>
<asp:TemplateField SortExpression="Username" HeaderText="Username">
<edititemtemplate>
<asp:DropDownList id="editUser" runat="server" DataSourceID="odsUsers" __designer:wfdid="w28" DataTextField="FullName" DataValueField="AccountName" SelectedValue='<%# Bind("Username") %>'></asp:DropDownList> <asp:RequiredFieldValidator id="rfvEditUser" runat="server" __designer:wfdid="w29" ErrorMessage="Select a user account" ValidationGroup='<%# Enum.GetName(typeof(ValidationGroup), ValidationGroup.EditUserComputer) %>' SetFocusOnError="True" ControlToValidate="editUser">*</asp:RequiredFieldValidator>
</edititemtemplate>
<footertemplate>
<asp:DropDownList id="newUser" runat="server" DataSourceID="odsUsers" __designer:wfdid="w7" DataTextField="FullName" DataValueField="AccountName"></asp:DropDownList> <asp:RequiredFieldValidator id="rfvNewUser" runat="server" __designer:wfdid="w8" ErrorMessage="Select a user account" ValidationGroup='<%# Enum.GetName(typeof(ValidationGroup), ValidationGroup.NewUserComputer) %>' SetFocusOnError="True" ControlToValidate="newUser">*</asp:RequiredFieldValidator>
</footertemplate>
<itemtemplate>
<asp:Label id="viewUser" runat="server" Text='<%# Bind("Username") %>' __designer:wfdid="w44"></asp:Label>
</itemtemplate>
</asp:TemplateField>
<asp:TemplateField SortExpression="Computer" HeaderText="Computer">
<edititemtemplate>
<asp:DropDownList id="editComputer" runat="server" DataSourceID="odsComputer" __designer:wfdid="w30" DataTextField="ComputerName" DataValueField="AccountName" SelectedValue='<%# Bind("Computer") %>'></asp:DropDownList>
<asp:RequiredFieldValidator id="rfvEditComputer" runat="server" __designer:wfdid="w31" ErrorMessage="Select a computer" ValidationGroup='<%# Enum.GetName(typeof(ValidationGroup), ValidationGroup.EditUserComputer) %>' SetFocusOnError="True" ControlToValidate="editComputer">*</asp:RequiredFieldValidator>
</edititemtemplate>
<footertemplate>
<asp:DropDownList id="newComputer" runat="server" DataSourceID="odsComputer" __designer:wfdid="w7" DataTextField="ComputerName" DataValueField="AccountName"></asp:DropDownList>
<asp:RequiredFieldValidator id="rfvNewComputer" runat="server" __designer:wfdid="w10" ErrorMessage="Select a computer" ValidationGroup='<%# Enum.GetName(typeof(ValidationGroup), ValidationGroup.NewUserComputer) %>' SetFocusOnError="True" ControlToValidate="newComputer">*</asp:RequiredFieldValidator>
</footertemplate>
<itemtemplate>
<asp:Label id="viewComputer" runat="server" __designer:wfdid="w15" Text='<%# Bind("Computer") %>'></asp:Label>
</itemtemplate>
</asp:TemplateField>
<asp:TemplateField SortExpression="IsDefault" HeaderText="Default">
<edititemtemplate>
<asp:CheckBox id="CheckBox1" runat="server" __designer:wfdid="w32" Checked='<%# Bind("IsDefault") %>' Enabled='<%# !((bool)Eval("IsDefault")) %>'></asp:CheckBox>
</edititemtemplate>
<footertemplate>
<asp:CheckBox id="newIsDefault" runat="server" __designer:wfdid="w20"></asp:CheckBox>
</footertemplate>
<itemtemplate>
<asp:Label id="viewIsDefault" runat="server" __designer:wfdid="w17" Text='<%# ((bool)Eval("IsDefault")) ? "Yes" : "" %>'></asp:Label>
</itemtemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<edititemtemplate>
<asp:Button id="btnUpdateUserComputer" runat="server" OnClick="btnUpdateUserComputer_Click" Text="Update" CausesValidation="True" CommandName="Update" ValidationGroup='<%# Enum.GetName(typeof(ValidationGroup), ValidationGroup.EditUserComputer) %>' __designer:wfdid="w41" />
<asp:Button id="btnCancelEditUserComputer" runat="server" onclick="btnCancelEditUserComputer_Click" Text="Cancel" CausesValidation="False" CommandName="Cancel" __designer:wfdid="w42" />
</edititemtemplate>
<footertemplate>
<asp:Button id="btnNewUserComputer" runat="server" __designer:wfdid="w43" Text="Add" ValidationGroup='<%# Enum.GetName(typeof(ValidationGroup), ValidationGroup.NewUserComputer) %>' OnClick="btnNewUserComputer_Click" CommandName="Insert" />
</footertemplate>
<itemtemplate>
<asp:Button id="btnEditUserComputer" runat="server" __designer:wfdid="w40" Text="Edit" CausesValidation="False" CommandName="Edit" OnClick="btnEditUserComputer_Click" />
</itemtemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<itemtemplate>
<asp:Button id="deleteUserComputer" runat="server" __designer:wfdid="w23" Text="Delete" Enabled='<%# !((bool)Eval("IsDefault")) %>' CausesValidation="False" OnClientClick='return confirm("Are you sure?")' CommandName="Delete" />
</itemtemplate>
</asp:TemplateField>
</Columns>
</cc1:MultisortIndicatorGridView>
<cc2:LLBLGenProDataSource2 ID="odsUserComputer" runat="server" AdapterTypeName="SBI.ITService.DAL.DatabaseSpecific.DataAccessAdapter, SBI.ITService.DALDBSpecific"
DataContainerType="EntityCollection" EntityFactoryTypeName="SBI.ITService.DAL.FactoryClasses.UsernameComputerEntityFactory, SBI.ITService.DAL">
<InsertParameters>
<asp:ControlParameter ControlID="newUser" Name="Username" PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="newComputer" Name="Computer" PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="newIsDefault" Name="IsDefault" PropertyName="Checked" Type="Boolean" />
</InsertParameters>
</cc2:LLBLGenProDataSource2>
<asp:ObjectDataSource ID="odsUsers" runat="server" OldValuesParameterFormatString="original_{0}"
SelectMethod="getAllEmployees" TypeName="SBI.ITSevice.DAL.ActiveDirectoryUser"></asp:ObjectDataSource>
<asp:ObjectDataSource ID="odsComputer" runat="server" OldValuesParameterFormatString="original_{0}"
SelectMethod="getAllgetComputers" TypeName="SBI.ITSevice.DAL.ActiveDirectoryComputer">
</asp:ObjectDataSource>
Joined: 05-Jul-2006
According to the docs LLBLGenProDataSource is for SelfService. I'm using the DataAdapter method which requires LLBLGenProDataSource2 if i'm not mistaken.
After rereading the docs i think i need to use the UnitofWork in the datasource control. I also found this posting on the forums.
I'm having trouble working with LivePersistance and UnitOfWork. If I understand the docs correctly UOW only exists if LivePersistance is false. If LivePersistance is false I can't get my GridView to display when the page is loaded. I've tried GridView.Bind() and DataSource.Select() but the records are not displayed. When LivePersistance=true DataSource.UOW=null (by design).
The only example in the docs was a design time databind with LivePersistance=true.
I also found this post when searching for UnitOfWork, but I think the issue has already been addressed. Since this was posted in May of '06 and the RC was July '06 http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=6140.
Any threads, blogs or documents (besides the manual) that explain the DataSourceControl or UnitOfWork in more detail would be appreciated.
Joined: 11-Nov-2006
I second this. I am having a difficult time getting my head round what is actually happening. Frans is there any chance you could post a small asp.net sample that uses persistence = false and makes use of UoW. Nothing special, just a simple grid edit/update/delete with a bit of error handling. It would really, really help.
Cheers,
Pete
Joined: 10-Mar-2006
Here is some code:
http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=6127&HighLight=1
It simply comes down to the fact that if you set LivePersistence to false, you have to add eventhandlers to the 3 events, if you want to do something when these events are raised.
E.g. if your form doesn't update data, you don't have to subscribe to the event PerformWork.
In the event args, you'll find the objects you need to work with. So if you set LivePersistence to false, you'll find in the eventargs passed to the eventhandler of PerformWork, the unitofwork object with the data of the action to take. You can commit that unitofwork or pass it on to other routines.
Be aware how asp.net works: if you change ONE row in a grid and click update, you'll get a call to PerformWork. This thus means that if you think you can collect the data for several actions in a single UoW you're mistaken. Unless you use a grid like ASPxGrid of DevExpress which works on the client and passes all work in 1 UoW.
You can't call Delete, Update etc as that wouldn't make much sense: the datasource objects are meant for databinding purposes. If you just want data to work with, fetch it in the code behind. The datasource controls are derived classes of DataSourceControl, the asp.net base class which is the base class for all datasource controls in asp.net.
That there's a 'Select' method is likely a leftover. There was / is hardly any documentation how to properly write a datasourcecontrol, so most of it is written with trial / error/ decompiles of existing datasourcecontrols. Not my way of writing software, but it was the only way to get something up and running, and when trial/error is used, often things get left behind.
Joined: 05-Jul-2006
Otis, thank you so much. The pieces are starting to fit together.
I still have 2 issues with my grid.
If LivePresistance=true the grid binds and all the rows appear including header and footer. If LivePersistance=false and the PreformWork method is defined my grid only displays the footer (where my insert controls are). So the grid is binding, but no data is returned from the database.
This may be my lack of understanding on how to retrieve records. here is the code.
protected void ods_PreformWork(object sender, SD.LLBLGen.Pro.ORMSupportClasses.PreformWorkEventArgs2 e)
{
using (DataAdapter da = new DataAdapter())
{
da.FetchEntityCollection(e.ContainedCollection, null);
}
}
I tried replacing null with e.filter (even though there is no filter for this collection), but no records are returned. This is a very simple dataobject. I just need the query to produce select * from mytable. The contained colleciton is correct. The factory is MytableFactory.
I am also have problems with the insert statement. I'm not getting errors, but it' also not inserting the record. There is a button in the footer with CommandName=Insert but this button does not seem to hook to the gridview like Edit/Update/Cancel/Delete do (which are also templated column/buttons within each row. When the add button is clicked it is not firing the PreformWork event.
Joined: 05-Jul-2006
Just for kicks I commented the DataSourceObject out of the code and removed the DataSourceID from the GridView.
In the code behind I defined an EntityCollection<MyEntity> similar to (if not just the same as) e.ContainedCollection in the PrefromSelect method. Fetched the collection without a filter and binded to the GridView. The records displayed like I thought they would.
If I stick with this method all my sorting, paging and editing needs to be hardcoded.
I stepped through the PreformSelect event. It does fire when the page is loaded. The e.ContainedCollection is loaded with the records I want, but they grid is displaying empty.
Any ideas why the DataSourceObject is not binding the results to the GridView?
Joined: 05-Jul-2006
I finally got the grid to load correctly! I did not define the PreformDBCount method. Now I can finally see my data.
Edit and delete are working properly as well. Now I just need to figure out how to connect the Add button in the template's footer to PreformWork and save the entity.
Joined: 05-Jul-2006
I now have everything working properly in terms of entity validation, selection, updates and deletes.
Inserts are still giving me a problem when i try to use the DataSourceObject. I found a workaround which disregards the DataSourceObject altogether, but it inserts the data to the db and popluates my data grid.
Is there a way to call the PreformWork method explicitly? Or, is there a way to populate the UnitOfWork property from code outside the PreformWork event? If I try to access MyDataSource.UnitOfWork in the AddRecord event the UnitOfWork is null I cannot assign values or commit changes.
I tried to create my own instance of a UOW2 object, set the DataAccessAdapter and Entity, but this made the db timeout on the MyDataSource.GetDBCount event.
I abandoned the UOW2 object and MyDataSource for a striaght DataAccessAdapter and Entity. After saving the entity I set MyDataSource.Refetch = True and GridView.BindData(); to retrieve the records. This works, but I figure it's a work around since I cannot do this through MyDataSource.
Is it by design that I cannot access UOW outside the DataSourceObject events? Is there a way to Save a new record via the DataSourceObject control from an event outside of the control Example: On button click assign insert values to DataSourceObject and Call UOW.Commit.
jmeckley wrote:
I now have everything working properly in terms of entity validation, selection, updates and deletes.
Inserts are still giving me a problem when i try to use the DataSourceObject. I found a workaround which disregards the DataSourceObject altogether, but it inserts the data to the db and popluates my data grid.
Inserts are often a bit tricky as they require a separate control, e.g. a formview. You can share a datasource control between a grid and a formview though.
Is there a way to call the PreformWork method explicitly? Or, is there a way to populate the UnitOfWork property from code outside the PreformWork event? If I try to access MyDataSource.UnitOfWork in the AddRecord event the UnitOfWork is null I cannot assign values or commit changes.
If you've set livepersistence to false, the datasourcecontrol will raise the PerformWork event when it's time to perform the work. It's declarative programming, so you define when what happens and sit back and relax till things have to happen The bound formview control (example) will call the datasourcecontrol to do an insert or update. When that happens, (ExecuteInsert or ExecuteUpdate are called by the bound control) PerformWork is raised and the eventargs of the event contain the data you need to perform the work, e.g. the UnitOfWork2 object etc.
Is it by design that I cannot access UOW outside the DataSourceObject events? Is there a way to Save a new record via the DataSourceObject control from an event outside of the control Example: On button click assign insert values to DataSourceObject and Call UOW.Commit.
The unitofwork is created when the performwork event is raised, as at THAT moment a unitofwork object is needed. The bound formview control knows when it's time to do an insert, i.e. when the user clicks Insert. The data then arrives at the ExecuteInsert method and from there the datasourcecontrol takes over and either raises PerformWork with all the data necessary to perform the insert, or does the work itself (if livepersistence is true).
It's a bit hard to track what the current state is of your form. If you don't use a formview control for inserts, you've to bypass the datasourcecontrol. Though my experience is that it's easier to use a formview control as you can then use the formview logic that it knows how to gather the info inside the form, pass it to the datasource etc.