datasource throws connectionstring property has not been initialized exception at design time

Posts   
 
    
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 06-Jul-2006 22:11:54   

Well, Otis, by this time I guess we both are wishing I had been more active in the beta! wink

Lets say you have EntityA that has a 1:n relationship with EntityB.

You add a property to EntityA called 'EntityBSummary' that looks like this:

public string EntityBSummary
{
    get
    {
        return string.Format("{0} associated Entities", this.EntityB.Count);
    }
}

Now, of course you can use entityA.EntityBSummary to get that text, all is fine and good and this code will work just fine.

However, if you put a grid on a webform and use an LLBLGenDataSource (selfservicing) and attach it to an EntityACollection, you will get an exception at design time, which shows up as the 'rendering' of the grid.

The exception says:

System.Reflection.TargetInvocationException: Property accessor 'EntityBSummary' on object FullNameSpace.EntityClasses.EntityA threw the following exception: 'The ConnectionString property has not been initialized.'

What do I need to do to avoid this?

(Everything works fine at runtime)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 07-Jul-2006 10:25:12   

WayneBrantley wrote:

Well, Otis, by this time I guess we both are wishing I had been more active in the beta! wink

Well, let say it's unfortunate wink .

Lets say you have EntityA that has a 1:n relationship with EntityB.

You add a property to EntityA called 'EntityBSummary' that looks like this:

public string EntityBSummary
{
    get
    {
        return string.Format("{0} associated Entities", this.EntityB.Count);
    }
}

Now, of course you can use entityA.EntityBSummary to get that text, all is fine and good and this code will work just fine.

However, if you put a grid on a webform and use an LLBLGenDataSource (selfservicing) and attach it to an EntityACollection, you will get an exception at design time, which shows up as the 'rendering' of the grid.

The exception says:

System.Reflection.TargetInvocationException: Property accessor 'EntityBSummary' on object FullNameSpace.EntityClasses.EntityA threw the following exception: 'The ConnectionString property has not been initialized.'

What do I need to do to avoid this?

(Everything works fine at runtime)

You trigger lazy loading in your property. At design time the values for the properties are read by the grid, that's a given, I can't avoid that unfortunately. What's more unfortunate is that the designmode checks are internal in the runtime lib, not exposed to the outside code. What you can do is a workaround:


public string EntityBSummary
{
    get
    {
        int count = 0;
        if(!this.IsNew)
        {
            count = this.EntityB.Count;
        }
        return string.Format("{0} associated Entities", count);
    }
}

This won't trigger lazy loading at design time as the entities are all new.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 07-Jul-2006 18:39:22   

Problem with your solution is:

EntityA entityA = new entityA(); EntityB entityB = new entityB();

entityA.EntityB.Add(entityB);

//now this line should print '1 associated entities' entityA.EntityBSummary;

but with your workaround, it will show '0 assocatied entities'

since entityA is still 'new'.

How do you avoid the lazy loading in your properties, like when it looks for 'EntityB' property?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 07-Jul-2006 19:30:42   

WayneBrantley wrote:

Problem with your solution is:

EntityA entityA = new entityA(); EntityB entityB = new entityB();

entityA.EntityB.Add(entityB);

//now this line should print '1 associated entities' entityA.EntityBSummary;

but with your workaround, it will show '0 assocatied entities'

since entityA is still 'new'.

How do you avoid the lazy loading in your properties, like when it looks for 'EntityB' property?

In your code it should find out that it's in design mode, however at the moment I don't see a way to retrieve that info, as that's internal in the runtime lib classes. An entity has an internal property Site. I'll see if I can make a protected property as well which returns that value for code like yours so you can test if you're in design mode and if so, don't trigger lazy loading.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 10-Jul-2006 11:37:37   

In the next build of the runtime libs, a protected property is available to you in the entities. You can use it like this:


public string OrderSummary
{
    get
    {
        if(base.InDesignMode)
        {
            return "# associated entities";
        }
        else
        {
            return string.Format("{0} associated entities", this.OrdersCollection.Count);
        }
    }
}

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 11-Jul-2006 02:32:20   

Excellent, and good timing - I was just going to bump you about this.

I am guessing next build will be available soon?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 11-Jul-2006 09:40:33   

Yes, today or tomorrow.

(edit) available now)

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 25-Sep-2006 04:18:00   

This thread is now active again. This bug is appearing again, but this time with generated code instead of add-on methods.

I have a class library which I add an XtraReport to from Developer Express. When I do that, I get a list of components from the LLBLGen project that I can drop onto the form (all the collection classes).

If I drop one of the components representing a collection of entities that do not have any 1:n relationships, it works fine.

However, if I drop one that has either direct 1:n relationships or one of the 'SomeCollectionViaSomeOtherCollection' relationships you get the same error as above.

Any help here?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 25-Sep-2006 09:37:44   

Apparently DevExpress' code triggers lazy loading (which means they read properties on the objects themselves). You also have this behavior on a winform? Because I havent' seen it.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 26-Sep-2006 05:46:18   

I dont use much in the way of winforms, so I cannot say for sure.

I figured the InDesignMode flag is not working in this particular case. (or is it not checked in every property?)

Any ideas what I can do about this?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 26-Sep-2006 10:22:25   

WayneBrantley wrote:

I dont use much in the way of winforms, so I cannot say for sure.

I figured the InDesignMode flag is not working in this particular case. (or is it not checked in every property?) Any ideas what I can do about this?

When a control or object (component) is placed onto a form (or better: container) in design mode in VS.NET, the 'Site' property is set. When the Site property is set, InDesignMode is set to true. 'Site' is a way to connect to the containing system more or less.

If the container doesn't set that property, the control / object of course doesn't know if it's design mode or runtime mode: for the control / object it's just the same: it is a live object and it's placed onto a form/container, which can be done at runtime at startup of a form or at design time when a user drags the component onto the form (which simply creates an instance of the class dragged onto the form as the form IS live.

My guess is that the report acts as a normal container so you can drag components onto it, but it doesn't set the Site property. Because that's not happening, the control/component/object doesn't know it's in design mode and the code simply acts as if it's at runtime: thus triggering lazy loading, which of course fails.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 27-Sep-2006 05:28:28   

Problem appears to be in the base code generated. I looked through it and could not find anywhere that it was checking for design mode.

I took an Entity that only had one relationship. Dropped it on the report and got the error. I then did an override on the related field with:

public override Company.DAL.CollectionClasses.SomeEntityCollection SomeEntity
{
   get { 
   if (!base.InDesignMode)
      return GetMultiSomeEntity(false); 
   else
      return null;
   }
}

This corrects the problem and the component drops on the design surface without error! smile

In anticipation of what this fix might be, I modified the first line to include the !base.InDesignMode in these two methods in entityInclude.template.

OneToMany...

public virtual <[RootNamespace]>.CollectionClasses.<[RelatedEntityName]>Collection GetMulti<[MappedFieldNameRelation]>(bool forceFetch, IEntityFactory entityFactoryToUse, IPredicateExpression filter)
        {
            if( (!_alreadyFetched<[MappedFieldNameRelation]> || forceFetch || _alwaysFetch<[MappedFieldNameRelation]>) && !base.IsSerializing && !base.IsDeserializing && !base.InDesignMode)

and ManyToMany...

public <[RootNamespace]>.CollectionClasses.<[RelatedEntityName]>Collection GetMulti<[MappedFieldNameRelation]>(bool forceFetch, IEntityFactory entityFactoryToUse)
        {
            if( ( !_alreadyFetched<[MappedFieldNameRelation]> || forceFetch || _alwaysFetch<[MappedFieldNameRelation]>) && !base.IsSerializing && !base.IsDeserializing && !base.InDesignMode)

After regenerating, everything works great as far as this is concerned. sunglasses

If it is indeed this simple, is this a change you can make to the templates (or an equivalent change where it needs to go)?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 27-Sep-2006 09:49:54   

great! simple_smile

WHen I read your posting I thought: why don't I run into this on a winform or webform, but in these situations, you only work with a collection, most of the time or a datasourcecontrol which hides everything for you.

I'll apply the fix to the templates, as this is easy to do simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 27-Sep-2006 15:42:19   

First, thanks for fixing the above!

Now, for one more related issue. When dropping these on the report - the report shows the related entities and you can pick their fields, etc. However, it does not show the m:1 related entities. I did some looking around and found that was because those properties have Browsable(false). The generated code states that this is done because the property is expensive and an alternative method is given. However, all this property does is call that method, so unsure why this is considered expensive. Here is prototype of that generated code:

/// <summary> Gets / sets related entity of type 'SomeEntity'. This property is not visible in databound grids.
/// Setting this property to a new object will make the load-on-demand feature to stop fetching data from the database, until you set this
/// property to null. Setting this property to an entity will make sure that FK-PK relations are synchronized when appropriate.</summary>
/// <remarks>This property is added for conveniance, however it is recommeded to use the method 'GetSingleEntityPropertName()', because 
/// this property is rather expensive and a method tells the user to cache the result when it has to be used more than once in the
/// same scope. The property is marked non-browsable to make it hidden in bound controls, f.e. datagrids.</remarks>
[Browsable(false)]
public virtual SomeEntity EntityPropertyName
{
    get { return GetSingleEntityPropertyName(false); }
    set
    {
        if(base.IsDeserializing)
        {
            SetupSyncEntityPropertyName(value);
        }
        else
        {
            if(value==null)
            {
                if(_entityPropertyName != null)
                {
                    _entityPropertyName.UnsetRelatedEntity(this, "EntityName");
                }
            }
            else
            {
                ((IEntity)value).SetRelatedEntity(this, "EntityName");
            }
        }
    }
}

Question is - Can we drop the Browsable(false) attribute on this method in the templates? By doing so, it caused that property to show up at design time. I made this change in the 2 places in that same template and they show up. (As a side note, XtraReports does NOT recogonize these as complex properties that should have related properties and I have reported this as a bug to them http://www.devexpress.com/issue=DB40895, although I will probably end up having to send in an example, will see)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 28-Sep-2006 11:43:26   

WayneBrantley wrote:

First, thanks for fixing the above!

Now, for one more related issue. When dropping these on the report - the report shows the related entities and you can pick their fields, etc. However, it does not show the m:1 related entities. I did some looking around and found that was because those properties have Browsable(false). The generated code states that this is done because the property is expensive and an alternative method is given. However, all this property does is call that method, so unsure why this is considered expensive. Here is prototype of that generated code:

The remark is about the discussion when you should use a property and when you should use a method. The MS guidelines say that when a property contains 'expensive' code (i.e. takes a relatively long time), you should use a method, not a property. The remark is there to prevent people from complaining that the code isn't compliant with MS guidelines. It IS compliant with the guidelines, the property is there for databinding purposes simple_smile

Question is - Can we drop the Browsable(false) attribute on this method in the templates? By doing so, it caused that property to show up at design time. I made this change in the 2 places in that same template and they show up. (As a side note, XtraReports does NOT recogonize these as complex properties that should have related properties and I have reported this as a bug to them http://www.devexpress.com/issue=DB40895, although I will probably end up having to send in an example, will see)

No, the attribute can't be dropped. The reason is that the attribute is used to weed out properties which shouldn't be returned to a grid or other bound control when it requests the propertydescriptors for the type to show in the control. If I remove the attribute, you'll get a column in a grid with 'Customer' when you list a set of orderentities which contain a property Customer, mapped on the m:1 relation order-customer.

The sad thing is: SOME controls are smart enough to drop these columns/properties themselves, but others aren't. So I have to do the filtering first.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 28-Sep-2006 19:36:56   

Otis wrote:

Question is - Can we drop the Browsable(false) attribute on this method in the templates? By doing so, it caused that property to show up at design time. I made this change in the 2 places in that same template and they show up. (As a side note, XtraReports does NOT recogonize these as complex properties that should have related properties and I have reported this as a bug to them http://www.devexpress.com/issue=DB40895, although I will probably end up having to send in an example, will see)

No, the attribute can't be dropped. The reason is that the attribute is used to weed out properties which shouldn't be returned to a grid or other bound control when it requests the propertydescriptors for the type to show in the control. If I remove the attribute, you'll get a column in a grid with 'Customer' when you list a set of orderentities which contain a property Customer, mapped on the m:1 relation order-customer.

The sad thing is: SOME controls are smart enough to drop these columns/properties themselves, but others aren't. So I have to do the filtering first.

Understood. I have already removed that attribute in my templates, so I did some testing.

Asp.WebGrid and other Asp databound controls - Ignores those complex types Telerik - Ignores those complex types Infragistics - puts those types in, and just displays the type name in those columns.

I did not receive any errors or anything from any components. So, Infragistics lists a field in its fieldlist that it is not smart enough to display (or smart enough to filter out), does it really matter? It elimates any advanced controls from using them - and as all these controls advance, they will soon be able to recogonize them better.

In short, is there any real damage to allowing those properties to be visible? (and is there another alternative other than me modifying the templates to get this behaviour)

As always, thanks for your great support and your great product.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 29-Sep-2006 12:57:53   

WayneBrantley wrote:

Otis wrote:

Question is - Can we drop the Browsable(false) attribute on this method in the templates? By doing so, it caused that property to show up at design time. I made this change in the 2 places in that same template and they show up. (As a side note, XtraReports does NOT recogonize these as complex properties that should have related properties and I have reported this as a bug to them http://www.devexpress.com/issue=DB40895, although I will probably end up having to send in an example, will see)

No, the attribute can't be dropped. The reason is that the attribute is used to weed out properties which shouldn't be returned to a grid or other bound control when it requests the propertydescriptors for the type to show in the control. If I remove the attribute, you'll get a column in a grid with 'Customer' when you list a set of orderentities which contain a property Customer, mapped on the m:1 relation order-customer.

The sad thing is: SOME controls are smart enough to drop these columns/properties themselves, but others aren't. So I have to do the filtering first.

Understood. I have already removed that attribute in my templates, so I did some testing.

Asp.WebGrid and other Asp databound controls - Ignores those complex types Telerik - Ignores those complex types Infragistics - puts those types in, and just displays the type name in those columns.

I did not receive any errors or anything from any components. So, Infragistics lists a field in its fieldlist that it is not smart enough to display (or smart enough to filter out), does it really matter? It elimates any advanced controls from using them - and as all these controls advance, they will soon be able to recogonize them better.

You could remove the columns from the grid, but the problem is that some people use auto-generate columns in grids, and they suddenly have these columns show up, so it's not removable.

In short, is there any real damage to allowing those properties to be visible? (and is there another alternative other than me modifying the templates to get this behaviour)

Sadly, it's the only way to make them visible. There's no other way: if I let them pass, they'll show up in designtime databinding and some grids. The sad thing is that there's no context info passed in when the properties are quested, so for example if you have an order entity in an ordercollection and you want to bind its customer.companyname to a textbox, it wont show up, because it's unclear to the routine (as that info isn't passed in) that the m:1 related object (which isn't viewed) should be returned.

As long as some controls are written so poorly, I can't enable it.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1255
Joined: 10-Mar-2006
# Posted on: 16-Oct-2006 20:31:13   

Otis, Just want to see if the above change (the approved one) has been made yet. I was going to update my version, did not see this change in the template change history.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39615
Joined: 17-Aug-2003
# Posted on: 16-Oct-2006 21:53:25   

Correct, it slipped through the cracks. flushed I've added it to the internal gemini system now so it should be added and tested later this week. If design time databinding for winforms fails with this, it's not added. I don't expect it to fail though.

(Fixed in next build)

Frans Bouma | Lead developer LLBLGen Pro