LLBLGenDatasource2 & ListView with multiple DataKeyNames.

Posts   
 
    
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 20-Mar-2009 18:53:47   

ORM support dll : 2.6.08.1211

When using the llblgendatasource2 with a listview, editing works fine when there is only one DataKeyName. However, when I have an entity with a primary key composed of two fields, editing does not work. The ItemUpdating event of from the list view has the datakeys filled out correctly however the llblgendatasource2 returns the entity to insert instead of to update in the unitofwork. The datakeynames for the list view are filled out as such : DataKeyNames="ContactGroupId, MemberContactId"

Is the llblgen datasource limited to only single field primary keys?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 20-Mar-2009 19:31:09   

Could you please post the relevant declarative aspx of this? Also, the DDL for that table (what fields, what type and what of those are PK)

David Elizondo | LLBLGen Support Team
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 20-Mar-2009 19:34:31   

daelmo wrote:

Could you please post the relevant declarative aspx of this? Also, the DDL for that table (what fields, what type and what of those are PK)

Sure here you go.



<table id="LV_Table" class="sp-tbl" cellspacing="0"  border="0" style="width:700px;border-collapse:collapse;">
            <tr runat="server" id="LV_Header" class="sp-tbl-hd-tr">
                        <th>
                            <asp:LinkButton ID="btn3"
                                runat="server" CommandName="Sort" 
                                CommandArgument="MemberName" Text="Member Name" />
                        </th>
                        <th>
                            <span>Note</span>
                        </th>
                        <th>&nbsp;</th>
                    </tr>
            <asp:ListView ID="MembersListView" runat="server" 
                DataKeyNames="ContactGroupId, MemberContactId"   
                DataSourceId="MemberDataSource"
                EnableViewState="true"
                >
                <LayoutTemplate>
                    
                                <tr id="itemPlaceholder" runat="server" />
                        
                </LayoutTemplate>
                <ItemTemplate>
                    <tr id="row" runat="server" class='<%# Container.DataItemIndex % 2 == 0 ? "sp-tbl-tr" : "sp-tbl-tr-alt" %>'>
                            <td  class="nobr"><%# (Container.DataItem as InfrastructureCentral.Data.DbModel.EntityClasses.ContactGroupMemberEntity).Contact.Name %></td>
                            <td><%# Eval("Note") %></td>
                            <td><asp:LinkButton ID="LB_Edit" runat="server" Text="EDIT" CssClass="redit" CommandName="Edit" ></asp:LinkButton> |
                            <asp:LinkButton ID="LB_Delete" runat="server" Text="DELETE" CssClass="redit" CommandName="Delete" ></asp:LinkButton></td>
                        </tr>
                </ItemTemplate>
                <EditItemTemplate>
                        <tr class='<%# Container.DataItemIndex % 2 == 0 ? "sp-tbl-tr" : "sp-tbl-tr-alt" %>'>
                            <td class="nobr"><%# (Container.DataItem as InfrastructureCentral.Data.DbModel.EntityClasses.ContactGroupMemberEntity).Contact.Name %></td>
                            <td><asp:TextBox ID="TB_Note" runat="server" Width="400px" Text='<%# Bind("Note") %>' TextMode="MultiLine"></asp:TextBox></td>
                            <td>
                                <asp:LinkButton ID="LB_Edit" runat="server" Text="Update" CssClass="redit" CommandName="Update"></asp:LinkButton> |
                                <asp:LinkButton ID="LinkButton1" runat="server" Text="Cancel" CssClass="redit" CommandName="Cancel"></asp:LinkButton></td>
                        </tr>
                </EditItemTemplate>
            </asp:ListView>
                <llblgenpro:LLBLGenProDataSource2 ID="MemberDataSource" runat="server" 
                    AdapterTypeName="InfrastructureCentral.Data.DbModel.Sql.DataAccessAdapter, InfrastructureCentral.Data.DbModel.Sql" 
                    DataContainerType="EntityCollection" 
                    EntityFactoryTypeName="InfrastructureCentral.Data.DbModel.FactoryClasses.ContactGroupMemberEntityFactory, InfrastructureCentral.Data.DbModel"
                    LivePersistence="False"
                    >
                </llblgenpro:LLBLGenProDataSource2>



ContactGroupMember

ContactGroupId UniqueIdentifier MemberContactId UniqueIdentifier Note Varchar(255)

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 21-Mar-2009 01:01:53   

Brandt,

I guess that the two UniqueIdentifier fields are the PK, right?

What do you mean when you say "doesn't work" (not firing, an exception, etc.)?

If possible please post the Generated sql when this happen.

David Elizondo | LLBLGen Support Team
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 21-Mar-2009 01:44:26   

daelmo wrote:

Brandt,

I guess that the two UniqueIdentifier fields are the PK, right?

What do you mean when you say "doesn't work" (not firing, an exception, etc.)?

If possible please post the Generated sql when this happen.

Yes, the two id columns are the Pks.

After updating an item in the ListView, the UnitOfWork that the datasource passes during the PerformWork event has an entity to insert. It should have an entity to update. Its like the datasource doesn't know how to handle the multiple keys so it just creates a new entity instead of finding the entity to update. I have confirmed that the Listview is passing the correct multiple keys. Hopefully this was a little clearer.

Thanks for helping.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 23-Mar-2009 04:13:06   

Hi Brandt.

I noticed you have LivePersistence="False" but you haven't a handler for the OnPerformWork event. This is necessary when you use LivePersistence False. Also, I didn't see this problem happen before. If you could make a tiny repro solution with Northwind, if possible (or send the DB script) and zip it (just code, no bin, dlls, etc) and attach it to this thread, that would be helpful to try to figure it out.

David Elizondo | LLBLGen Support Team
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 23-Mar-2009 13:59:50   

daelmo wrote:

Hi Brandt.

I noticed you have LivePersistence="False" but you haven't a handler for the OnPerformWork event. This is necessary when you use LivePersistence False. Also, I didn't see this problem happen before. If you could make a tiny repro solution with Northwind, if possible (or send the DB script) and zip it (just code, no bin, dlls, etc) and attach it to this thread, that would be helpful to try to figure it out.

I attached all of the event handlers for the datasource in the OnInit event for the page. I will create reproduce and attach.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 23-Mar-2009 14:27:58   

We will be waiting for your repro.

But I bet this would have worked if you set LivePersistence to true, in other words I giess the problem is in the code of the PerformWork event.

Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 23-Mar-2009 14:57:59   

Walaa wrote:

We will be waiting for your repro.

But I bet this would have worked if you set Liveersistence to true, in other words I giess the problem is in the code of the PerformWork event.

yea, i figured it out. Here was the problem (developer way to tired when writing code error). I have a form that does not save the inserts and updates to the listview until the user hits save at the bottom of the form. The inserts, updates and deletes were saved in session and then passed back to the datasource to rebind the grid. So when I updated an inserted item (which i kept trying because I didn't want to update the original test data) the UnitOfWork would return an item to insert which is correct. I would then add the item again.

I can solve this by setting the DoNotPerformAddIfPresent property to true on the collection. *** Update **** DoNotPerformAddIfPresent only works with fetched entities as the test for equality for new entities does not compare the primary keys. I will find a different way.

Thanks for your help! This one my fault definitely.

Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 23-Mar-2009 16:41:19   

Actually the way the entity equality works is really weird. The llblgendatasource returns the same entity that was originally inserted. It has the same objectId and same primary fields values. However the orginal entity in the collection and the entity returned by the datasource do not equal. So (o) will denote original entity, (u) will denote updated entity.

Both u and o are new and the same object.

o == u; returns FALSE.
o.ObjectId = u.ObjectId; returns TRUE. o.Fields == u.Fields; returns FALSE.
o.Fields.GetHashCode == u.Fields.GetHashCode; returns TRUE.

In the equality code below from EntityBase2, was it intended that the Entity.Equals of two new entities would call the equality objects and not the equality of the fields?



public override bool Equals(object obj)
{
    IEntity2 entity = obj as IEntity2;
    if (entity == null)
    {
        return false;
    }
    if (!base.GetType().Equals(obj.GetType()))
    {
        return false;
    }
    if ((this._fields == null) || (entity.Fields == null))
    {
        return false;
    }
    if (!this._isNew && !entity.IsNew)
    {
        return this._fields.Equals(entity.Fields);
    }
    return (this == entity);
}




Maybe change this

if (!this._isNew & !entity.IsNew)
// two falses would make a true for both new entities. 




Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 23-Mar-2009 17:42:51   

Nevermind I figured it out. I was being hit by serialization to view state. The version of the entity i had in session was not the same as the one the LLBLGendatasource uses because it was serialized and deserialized. Having the datasource store in session instead produces the behavior I want. I need to rethink this whole thing.