collection addnew method error

Posts   
1  /  2  /  3
 
    
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 06-Jul-2006 19:33:23   

well, you definately found the problem. E.value is nothing in the format function. maybe there is a bug in the vb templates for this?

I double checked my project properties for llbl gen.

ConvertNulledReferenceTypesToDefaultValue is true

GenerateNullableFieldsAsNullabeTypes is false.

All fields on the entity that I am having the problems with have the (Net 2.0) generate as nullable type unchecked and grayed out as sql won't allow nulls in that table.

?sender {System.Windows.Forms.Binding} System.Windows.Forms.Binding: {System.Windows.Forms.Binding}

?e.DesiredType "System.Int32" System.RuntimeType: "System.Int32" Assembly: {System.Reflection.Assembly} AssemblyQualifiedName: "System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Attributes: 1057033 BaseType: "System.ValueType" ContainsGenericParameters: False DeclaringMethod: {"Method may only be called on a Type for which Type.IsGenericParameter is true."} DeclaringType: Nothing DefaultBinder: {System.DefaultBinder} Delimiter: "."c EmptyTypes: {Length=0} FilterAttribute: {System.Reflection.MemberFilter} FilterName: {System.Reflection.MemberFilter} FilterNameIgnoreCase: {System.Reflection.MemberFilter} FullName: "System.Int32" GenericParameterAttributes: {"Method may only be called on a Type for which Type.IsGenericParameter is true."} GenericParameterPosition: {"Method may only be called on a Type for which Type.IsGenericParameter is true."} GUID: {System.Guid} HasElementType: False IsAbstract: False IsAnsiClass: True IsArray: False IsAutoClass: False IsAutoLayout: False IsByRef: False IsClass: False IsCOMObject: False IsContextful: False IsEnum: False IsExplicitLayout: False IsGenericParameter: False IsGenericType: False IsGenericTypeDefinition: False IsImport: False IsInterface: False IsLayoutSequential: True IsMarshalByRef: False IsNested: False IsNestedAssembly: False IsNestedFamANDAssem: False IsNestedFamily: False IsNestedFamORAssem: False IsNestedPrivate: False IsNestedPublic: False IsNotPublic: False IsPointer: False IsPrimitive: True IsPublic: True IsSealed: True IsSerializable: True IsSpecialName: False IsUnicodeClass: False IsValueType: True IsVisible: True MemberType: TypeInfo {32} MetadataToken: 33554623 Missing: {System.Reflection.Missing} Module: {System.Reflection.Module} Name: "Int32" Namespace: "System" ReflectedType: Nothing StructLayoutAttribute: {System.Runtime.InteropServices.StructLayoutAttribute} TypeHandle: {System.RuntimeTypeHandle} TypeInitializer: Nothing UnderlyingSystemType: "System.Int32"

?e.Value Nothing

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 06-Jul-2006 23:46:05   

Is the property in code generated as Nullable(Of Integer) ? Or is it generated as System.Int32 ? (thus in the entity class)

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 10-Jul-2006 14:19:34   

Otis wrote:

Is the property in code generated as Nullable(Of Integer) ? Or is it generated as System.Int32 ? (thus in the entity class)

Each of the properties is a standard .net type

Public Overridable Property [AccountMasterId]() As System.Int32
            Get
                Dim valueToReturn As Object = MyBase.GetCurrentFieldValue(CType(VoucherDetailFieldIndex.AccountMasterId, Integer))
                If valueToReturn Is Nothing Then
                    valueToReturn = TypeDefaultValue.GetDefaultValue(GetType(System.Int32))
                End If
                Return CType(valueToReturn, System.Int32)
            End Get
            Set
                SetNewFieldValue(CType(VoucherDetailFieldIndex.AccountMasterId, Integer), value)
            End Set
        End Property

AND

Public Overridable Property [PostingAmount]() As System.Decimal
            Get
                Dim valueToReturn As Object = MyBase.GetCurrentFieldValue(CType(VoucherDetailFieldIndex.PostingAmount, Integer))
                If valueToReturn Is Nothing Then
                    valueToReturn = TypeDefaultValue.GetDefaultValue(GetType(System.Decimal))
                End If
                Return CType(valueToReturn, System.Decimal)
            End Get
            Set
                SetNewFieldValue(CType(VoucherDetailFieldIndex.PostingAmount, Integer), value)
            End Set
        End Property
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 11-Jul-2006 11:14:05   

I must say, I'm running out of options.. flushed . I have no idea where to look what's wrong. I fail to reproduce it here, which is likely caused by the fact that my testsetup is too simple compared to your complex stack of controls interacting with eachother.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 11-Jul-2006 13:56:34   

OK. Let me see if I can figure it out or get you a demo project that does it.

Thanks.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 11-Jul-2006 14:42:20   

Thanks, and sorry if I'm not of help at this point. Good luck with the repro. Let me know if you need any more info.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 11-Jul-2006 20:37:06   

ok I sorta duplicated it with the code below


Imports SD.LLBLGen.Pro.ORMSupportClasses
Imports Csi.CsiBusinessBase
Imports Csi.CsiBusinessBase.CollectionClasses
Imports Csi.CsiBusinessBase.EntityClasses
Imports Csi.CsiBusinessBase.HelperClasses

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim col As VoucherMasterCollection = New VoucherMasterCollection
        Dim filter As IPredicateExpression = New PredicateExpression
        filter.AddWithAnd(VoucherMasterFields.Id >= 5 And VoucherMasterFields.Id <= 10)

        col.GetMulti(filter)

        UltraGrid1.DisplayLayout.MaxBandDepth = 1
        UltraGrid1.DataSource = col

    End Sub

    Private Sub Binding_format(ByVal sender As Object, ByVal e As ConvertEventArgs)

    End Sub

    Private Sub UltraGrid1_AfterRowActivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles UltraGrid1.AfterRowActivate
        Dim vch As VoucherMasterEntity = DirectCast(UltraGrid1.ActiveRow.ListObject, VoucherMasterEntity)

        UltraTextEditor1.DataBindings.Clear()

        UltraTextEditor1.DataBindings.Add("Text", vch.VoucherDetail, "PostingAmount")
        AddHandler UltraTextEditor1.DataBindings(0).Format, AddressOf Binding_format

        Dim det As VoucherDetailEntity = DirectCast(vch.VoucherDetail.EntityFactoryToUse.Create, VoucherDetailEntity)
        vch.VoucherDetail.Add(det)

        Dim currencymanagerSys48 As CurrencyManager
        currencymanagerSys48 = CType(Me.BindingContext(vch.VoucherDetail), CurrencyManager)
        currencymanagerSys48.Position = vch.VoucherDetail.Count - 1

    End Sub
End Class


it's a simple grid with parent entities in it. You click one and it binds the first detail entity to a single text box.

It doesn't blow up, but the value of the textbox and the binding_format event get a nothing for fields that aren't defaulted. The blow up is the result of heavily modified controls we have that can't handle nulls. Even if we fix the controls though, we don't want a null value in the boxes. What's the next step for this?

I can send you my generated code if you want, or you can give me some info on what to check if that's easier. Some how, the underlying null value is getting used for binding instead of the value of the property. I can put a breakpoint in the property get method of the entitybase class and it never gets hit, even though the control is now bound to it.

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 12-Jul-2006 11:22:31   

You're using the infragistics grid. We don't have a license for that grid other than 2004.1. Could you try to repro it with the normal datagridview ?

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 12-Jul-2006 16:23:42   

I'll try, but I don't think it matters. It's not the grid that does it, it's binding the textbox to a new entity. The new entity's fields are all nothing instead of a default value.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 12-Jul-2006 21:10:38   

Please give it a try with the normal grid, as I couldn't repro it with the normal grid.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 14-Jul-2006 17:07:49   

ok here's the code for using a standard grid.

It does it also. If you look at the value of e.value in binding_format, it's always nothing on the new row. The standard text box ignores it and leaves the text property "" when I want it to be 0 etc.


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim col As VoucherMasterCollection = New VoucherMasterCollection
        Dim filter As IPredicateExpression = New PredicateExpression
        filter.AddWithAnd(VoucherMasterFields.Id >= 5 And VoucherMasterFields.Id <= 10)

        col.GetMulti(filter)
        DataGridView1.DataSource = col
    End Sub

    Private Sub Binding_format(ByVal sender As Object, ByVal e As ConvertEventArgs)

    End Sub

    Private Sub DataGridView1_RowEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.RowEnter
        If DataGridView1.SelectedRows.Count = 0 Then Return
        Dim vch As VoucherMasterEntity = DirectCast(DataGridView1.SelectedRows(0).DataBoundItem, VoucherMasterEntity)

        TextBox1.DataBindings.Clear()

        TextBox1.DataBindings.Add("Text", vch.VoucherDetail, "PostingAmount")
        AddHandler TextBox1.DataBindings(0).Format, AddressOf Binding_format

        Dim det As VoucherDetailEntity = DirectCast(vch.VoucherDetail.EntityFactoryToUse.Create, VoucherDetailEntity)
        vch.VoucherDetail.Insert(0, det)

        Dim currencymanagerSys48 As CurrencyManager
        currencymanagerSys48 = CType(Me.BindingContext(vch.VoucherDetail), CurrencyManager)
        currencymanagerSys48.Position = 0
    End Sub

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 14-Jul-2006 17:16:23   

Thanks, though now I know what event you're using, I think I know what's wrong. As you use the RowEnter event, the IEditableObject interface's BeginEdit is just called (I think, the docs on RowEnter are very vague). This can mean the events are occuring before AddNew is called on the bound collection. (I'm not sure, have to check).

Either way, thanks for the repro code. I'll try to reproduce it with an entity and your code and will report back to you in this thread.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 14-Jul-2006 20:46:36   

thanks, I'll play with it some more also. Remember too that we don't use the regular grid in our project and wouldn't be using that rowenter method.

in my tests, the binding_format function gets called right after the vch.voucherdetail.insert(0,det) gets fired if that helps any.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 17-Jul-2006 13:50:49   

It was a little hard to reproduce as the routine often didn't proceed, but it finally made it to the eventhandler.

As you perform an insert, the collection (in your case the VoucherDetail collection) raises through its view a ListChanged event with the parameter 'Reset' as every row in the view changed position, as you inserted a new one.

That event, gets picked up by the currency manager according to the call stack, passed on to the binding manager and then ends up in the Binding_Format routine.

How it comes up with the null value is beyond me, nothing gets read from the bound objects. I think it's an issue with the order in which things are taken place. I'll reshuffle the code a bit to see what fixes it.

(edit). Found it. As you bind a collection to the textbox, property descriptors are created. EntityPropertyDescriptor instances to be exact. these have code internally to read the CurrentValue when GetValue is called. Which makes them to return null, instead of the default value.

I've to do some serious testing before changing this, as it could be changing this will break the code with grids and nullabletypes. Stay tuned.

(edit). the change in that property descriptor fixed it. I now have to test if this change breaks nullable typed properties in a grid.

(edit) All tests seem to suggest this works smoothly. The only change made is that the GET of the value through the property descriptor now also reads the field property instead of currentvalue. The setter already used the property. Will now see that the old datagrid indeed can handle this.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 17-Jul-2006 15:14:33   

Fixed in next build. (available today or tomorrow)

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 18-Jul-2006 20:51:27   

Great!! Thanks for all the work on it. I'm glad you finally found it.

Fyi for anyone using vb.net, in my testing, i generated a c# version of the project to see if it was just a problem just in the vb templates or both. The c# version compiles in 16 seconds compared to 2 mins in vb.net for our 150 table db project. the whole app runs noticably faster now, and uses significantly less memory. about 100-120 meg less.

I managed to get management to agree to keep it in c# simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 18-Jul-2006 22:24:37   

the app runs with lower memory footprint? that's odd. It should be the same.

Compilation is slower indeed, that's due to the vb.net background compiler.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 19-Jul-2006 13:51:52   

yeah, it's a smaller foot print, but we didn't really test that too well. Could be the change to the 2.0 llbl also. I don't remember looking at it after we moved over so it may just be the upgrade. It runs noticably faster now though. Several people have commented on this from our team. searchs that return collections are better and forms seem more responsive.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 19-Jul-2006 13:53:41   

jspanocsi wrote:

yeah, it's a smaller foot print, but we didn't really test that too well. Could be the change to the 2.0 llbl also. I don't remember looking at it after we moved over so it may just be the upgrade. It runs noticably faster now though. Several people have commented on this from our team. searchs that return collections are better and forms seem more responsive.

Yes v2.0 has much lower memory footprint and entity collection fetches are much faster (all bottlenecks which could be removed are removed wink ).

I hope to release the fix for the bug you ran into later today.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 19-Jul-2006 15:18:37   

Otis wrote:

jspanocsi wrote:

yeah, it's a smaller foot print, but we didn't really test that too well. Could be the change to the 2.0 llbl also. I don't remember looking at it after we moved over so it may just be the upgrade. It runs noticably faster now though. Several people have commented on this from our team. searchs that return collections are better and forms seem more responsive.

Yes v2.0 has much lower memory footprint and entity collection fetches are much faster (all bottlenecks which could be removed are removed wink ).

I hope to release the fix for the bug you ran into later today.

Umm, you sure it's not already released? simple_smile

I got the 17-jul-2006 runtime libraries when you posted the other day saying you had found the problem and would be fixed today or tomorrow and they fixed it.

I have another small problem now though. This one is just as weird. Everything works great except for date binding. If the field is a date time and the infragistics ultradate box is on a user control, it won't databind fully. When you leave the date field, it clears it and makes the date the date.minvalue. It works fine if the control is on a form, just not on a user control using the binding code like I posted above. Any ideas on this one? I'm not sure where to even start on it.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 19-Jul-2006 16:10:09   

jspanocsi wrote:

Otis wrote:

jspanocsi wrote:

yeah, it's a smaller foot print, but we didn't really test that too well. Could be the change to the 2.0 llbl also. I don't remember looking at it after we moved over so it may just be the upgrade. It runs noticably faster now though. Several people have commented on this from our team. searchs that return collections are better and forms seem more responsive.

Yes v2.0 has much lower memory footprint and entity collection fetches are much faster (all bottlenecks which could be removed are removed wink ).

I hope to release the fix for the bug you ran into later today.

Umm, you sure it's not already released? simple_smile

I got the 17-jul-2006 runtime libraries when you posted the other day saying you had found the problem and would be fixed today or tomorrow and they fixed it.

ah yes, I checked the wrong logs simple_smile the build of the 17th indeed contains the fix simple_smile

I have another small problem now though. This one is just as weird. Everything works great except for date binding. If the field is a date time and the infragistics ultradate box is on a user control, it won't databind fully. When you leave the date field, it clears it and makes the date the date.minvalue. It works fine if the control is on a form, just not on a user control using the binding code like I posted above. Any ideas on this one? I'm not sure where to even start on it.

It now returns the default value for the field if it's null. The default value for a datetime field is DateTime.MinValue. Hence the minvalue binding.

Perhaps best to make that field nullable in the designer and (if possible) make the control display the current date if the value is null.

Frans Bouma | Lead developer LLBLGen Pro
jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 19-Jul-2006 16:30:23   

I don't mind it being the min value or blank to start with, but the problem is that once you change it, it won't take it. It reverts back to being the minvalue nomatter what you set it to. It's like it's only binding 1 way. I'll try making it nullable and see if that helps.

Thanks.

jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 19-Jul-2006 16:39:55   

ok i tried it as a nullable type for the date field and it didn't help. The box still clears itself when you leave it.

jspanocsi
User
Posts: 145
Joined: 04-Mar-2005
# Posted on: 19-Jul-2006 18:22:05   

I tried some of the older version I have also, and found that it doesn't do this in the vb.net version. It broke when we went to the c# llbl version. Not sure why though. The definition of the property that does this is the same between both versions.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 19-Jul-2006 22:18:38   

Hmm. If you set a breakpoint in the property could you see if it reaches the property? Also could you set a breakpoint in the entity's SetNewFieldValue method and see what the base class call returns?

Frans Bouma | Lead developer LLBLGen Pro
1  /  2  /  3