- Home
- LLBLGen Pro
- Bugs & Issues
How to use LivePersistence="false
I am trying to play with an Adapter template project that I just generated. I cannot figure out how to use LivePersistence="false". I can fetch the data just fine with a PerformSelect event handler. But I cannot figure out how to do the updates. The UnitOfWork property is always null. I'm using a GridView. Does anyone have a simple example of what is required to do this?
The updates have to be done by a postback of the form, where you then read the UnitOfWork object from the datasourcecontrol:
protected void Button2_Click( object sender, EventArgs e )
{
if( llblgenDS2.UnitOfWorkObject != null )
{
using( DataAccessAdapter adapter = new DataAccessAdapter() )
{
// persist uow
UnitOfWork2 uow = llblgenDS2.UnitOfWorkObject;
uow.Commit( adapter, true );
llblgenDS2.Refetch = true;
}
}
}
I tried that, but the UnitOfWork was always null.
Things work great if I choose LivePersistence="true", but I want to inspect the changes before I commit them.
JohnRLewis wrote:
I tried that, but the UnitOfWork was always null.
Things work great if I choose LivePersistence="true", but I want to inspect the changes before I commit them.
Do you use paging? If so, if you edit something on page 1, and you then move to page 2, the data is destroyed. Is that the case in your scenario?
(edit) to elaborate a bit on this: paging using server side paging (thus paging switch on on the datasourcecontrol) loads the page of data into the contained entity collection. If the user moves to another page, the control thus loads another page of data, destroying the older page of data. It was impossible to keep track of the older pages, as that would accumulate the data in the control, because what if the user moves back and forth between pages?
I see this behavior in my testpage with filters based on selectparameters. When I edit a row, the change is made in the entity, but then the control gets a loadcomplete event which makes it gather the selectparameter values again, which cause the control to flag it's changed which means the bound controls will make a fetch, so the change is destroyed because the same data is fetched again.
In the May 9th build, the UnitOfWork property seems to be returning an object, but my code is still not working they way I was expecting. No records ever get updated in the database.
The code below is a simplified version of what I am trying to do in a real application. Upon selecting a record from a drop down, a FormView displays that record in Edit mode. When the user clicks Update, the database should be updated.
Please let me know if I am doing something wrong, or if the LLBLGenProDataSource2 is still exhibiting a bug.
P.S. I love llblgen!!!
<llblgen:LLBLGenProDataSource2 ID="MyDataSource1" runat="server"
AdapterTypeName="Boeing.CAT.BoeSysConfig.DataLayer.DatabaseSpecific.DataAccessAdapter, Boeing.CAT.BoeSysConfig.DataLayerDBSpecific"
DataContainerType="EntityCollection"
EntityFactoryTypeName="Boeing.CAT.BoeSysConfig.DataLayer.FactoryClasses.EthernetDNSNameEntityFactory, Boeing.CAT.BoeSysConfig.DataLayer" />
<llblgen:LLBLGenProDataSource2 ID="MyDataSource2" runat="server"
AdapterTypeName="Boeing.CAT.BoeSysConfig.DataLayer.DatabaseSpecific.DataAccessAdapter, Boeing.CAT.BoeSysConfig.DataLayerDBSpecific"
DataContainerType="EntityCollection"
EntityFactoryTypeName="Boeing.CAT.BoeSysConfig.DataLayer.FactoryClasses.EthernetDNSNameEntityFactory, Boeing.CAT.BoeSysConfig.DataLayer" LivePersistence="False" OnPerformGetDbCount="MyDataSource2_PerformGetDbCount" OnPerformSelect="MyDataSource2_PerformSelect" >
<SelectParameters>
<asp:Parameter DefaultValue="-1" Name="EthernetDNSNameID" />
</SelectParameters>
</llblgen:LLBLGenProDataSource2>
<asp:DropDownList ID="MyDropDown" runat="server"
DataSourceID="MyDataSource1"
DataTextField="DNSName"
DataValueField="EthernetDNSNameID"
AutoPostBack="true"
OnDataBound="MyDropDown_DataBound"
OnSelectedIndexChanged="MyDropDown_SelectedIndexChanged">
</asp:DropDownList>
<asp:FormView ID="MyFormView" runat="server" DataSourceID="MyDataSource2" DefaultMode="Edit" OnItemUpdated="MyFormView_ItemUpdated" DataKeyNames="EthernetDNSNameID">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("DNSName") %>' />
<asp:LinkButton ID="LinkButton1" runat="server" Text="Update" CommandName="Update" />
</EditItemTemplate>
</asp:FormView>
protected void MyDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
MyDataSource2.SelectParameters.Clear();
MyDataSource2.SelectParameters.Add("EthernetDNSNameID", TypeCode.Int32, ((DropDownList)sender).SelectedValue);
MyDataSource2.Refetch = true;
MyFormView.DataBind();
}
protected void MyDropDown_DataBound(object sender, EventArgs e)
{
((DropDownList)sender).Items.Insert(0, new ListItem("Select...", "-1"));
}
protected void MyDataSource2_PerformSelect(object sender, SD.LLBLGen.Pro.ORMSupportClasses.PerformSelectEventArgs2 e)
{
using (DataAccessAdapter da = new DataAccessAdapter())
{
da.FetchEntityCollection(e.ContainedCollection, e.Filter, 0, e.Sorter, e.PrefetchPath);
}
}
protected void MyDataSource2_PerformGetDbCount(object sender, SD.LLBLGen.Pro.ORMSupportClasses.PerformGetDbCountEventArgs2 e)
{
using (DataAccessAdapter da = new DataAccessAdapter())
{
e.DbCount = da.GetDbCount(e.ContainedCollection, e.Filter);
}
}
protected void MyFormView_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
{
UnitOfWork2 uow = MyDataSource2.UnitOfWorkObject;
if (uow != null)
{
using (DataAccessAdapter da = new DataAccessAdapter())
{
uow.Commit(da);
}
}
MyDataSource1.Refetch = true;
MyDropDown.DataBind();
}
Instead of MyFormView_ItemUpdated, bind to the PerformWork event of the datasourcecontrol. You should get the data to update there. This is a new event, added to overcome problems with the live persistence and uow's.
You also don't have to set Refetch to true anymore, that's been taken care of.
Example:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default6.aspx.cs" Inherits="Default6" %>
<%@ Register Assembly="SD.LLBLGen.Pro.ORMSupportClasses" Namespace="SD.LLBLGen.Pro.ORMSupportClasses" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<cc1:LLBLGenProDataSource2 ID="LLBLGenProDataSource2_1" runat="server" AdapterTypeName="UnitTests.Dal.Adapter.DatabaseSpecific.DataAccessAdapter, UnitTests.Dal.AdapterDBSpecific" DataContainerType="EntityCollection" EntityFactoryTypeName="UnitTests.Dal.Adapter.FactoryClasses.AddressEntityFactory, UnitTests.Dal.Adapter" LivePersistence="False" OnPerformWork="LLBLGenProDataSource2_1_PerformWork">
</cc1:LLBLGenProDataSource2>
<asp:FormView ID="FormView1" runat="server" DataKeyNames="AddressId" DataSourceID="LLBLGenProDataSource2_1" DefaultMode="Insert">
<InsertItemTemplate>
AddressId:
<asp:TextBox ID="AddressIdTextBox" runat="server" Text='<%# Bind("AddressId") %>'></asp:TextBox><br />
StreetName:
<asp:TextBox ID="StreetNameTextBox" runat="server" Text='<%# Bind("StreetName") %>'></asp:TextBox><br />
HouseNumber:
<asp:TextBox ID="HouseNumberTextBox" runat="server" Text='<%# Bind("HouseNumber") %>'></asp:TextBox><br />
City:
<asp:TextBox ID="CityTextBox" runat="server" Text='<%# Bind("City") %>'></asp:TextBox><br />
Country:
<asp:TextBox ID="CountryTextBox" runat="server" Text='<%# Bind("Country") %>'></asp:TextBox><br />
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Insert"></asp:LinkButton>
<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
</InsertItemTemplate>
<ItemTemplate>
AddressId:
<asp:Label ID="AddressIdLabel" runat="server" Text='<%# Eval("AddressId") %>'></asp:Label><br />
StreetName:
<asp:Label ID="StreetNameLabel" runat="server" Text='<%# Bind("StreetName") %>'></asp:Label><br />
HouseNumber:
<asp:Label ID="HouseNumberLabel" runat="server" Text='<%# Bind("HouseNumber") %>'></asp:Label><br />
Zipcode:
<asp:Label ID="ZipcodeLabel" runat="server" Text='<%# Bind("Zipcode") %>'></asp:Label><br />
City:
<asp:Label ID="CityLabel" runat="server" Text='<%# Bind("City") %>'></asp:Label><br />
Country:
<asp:Label ID="CountryLabel" runat="server" Text='<%# Bind("Country") %>'></asp:Label><br />
TestRunId:
<asp:Label ID="TestRunIdLabel" runat="server" Text='<%# Bind("TestRunId") %>'></asp:Label><br />
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete"></asp:LinkButton>
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="New"></asp:LinkButton>
</ItemTemplate>
</asp:FormView>
</div>
</form>
</body>
</html>
codebehind:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using UnitTests.Dal.Adapter.DatabaseSpecific;
public partial class Default6 : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e )
{
}
protected void LLBLGenProDataSource2_1_PerformWork( object sender, SD.LLBLGen.Pro.ORMSupportClasses.PerformWorkEventArgs2 e )
{
using( DataAccessAdapter adapter = new DataAccessAdapter() )
{
e.Uow.Commit( adapter, true );
}
}
}
Joined: 14-Nov-2005
I'm working on the same issue and thanks for the clarification and example.
This is more of a request for advice. What would be the best approach if you are push the persist operation to a business layer that may involve transactions? With the objectdatasource you can pass the object to the business layer method specified by the DataObjectTypeName and InsertMethod properties.
With LLBLGenProDataSource2, would you pass the UnitOfWork to the business layer and manage the transaction there?
If you've opted for livepersistence=false, you indeed could do that. You can also simply collect the work in a second UoW object, every time PerformWork is raised. This second UoW is then stored in the session for example. You can simply move work from one uow to another by reading the elements from one and adding the contents to the other.
Then you add a button to the page which says 'Save' and in that handler you pass the uow you used to collect work to the BL tier and use a transaction there.