Null exception when using adaptor.DeleteEntityCollection

Posts   
 
    
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 27-Nov-2009 07:23:27   

I am using This IConcurrencyPredicateFactory to set transactions to check a timestamp field

    public class GenericConcurrencyFilterFactory : IConcurrencyPredicateFactory
    {
        public IPredicateExpression CreatePredicate(
            ConcurrencyPredicateType predicateTypeToCreate,
            object containingEntity)
        {
            var entity = (EntityBase2)containingEntity;

            var timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

            IPredicateExpression expression = new PredicateExpression();

            switch (predicateTypeToCreate)
            {
                case ConcurrencyPredicateType.Save:
                case ConcurrencyPredicateType.Delete:
                    expression.Add(timestampField == entity.Fields["Concurrency"].DbValue);
                    break;
            }
            return expression;
        }
    }

All failry standard

I am fetching an entity collection of user dictionary words which I persist in memory and out to disk (its easier to use a standard file for the spelling checker control that I am using)

I do this

        public CustomUserDictionary(string connectionString, string userAccount)
        {
            // use Isolated Storage not the executing assembly location
            //
            //string appPath = Path.GetDirectoryName
            //  (Assembly.GetAssembly(typeof(CustomUserDictionary)).Location);
            string appPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

            UserDictionary = Path.Combine(appPath, WardenIIDictionaries.USER_DICTIONARY_NAME);

            using (var adaptor = new DataAccessAdapter(connectionString))
            {
                try
                {
                    connection_String = connectionString;
                    user_Account = userAccount;
                    wordList = new EntityCollection(new DictionaryEntityFactory());
                    deletedWords = new EntityCollection(new DictionaryEntityFactory());
                    wordList.ConcurrencyPredicateFactoryToUse = new GenericConcurrencyFilterFactory();
                    deletedWords.ConcurrencyPredicateFactoryToUse = new GenericConcurrencyFilterFactory();
                    userWordList = new RelationPredicateBucket();
                    userWordList.PredicateExpression.Add(DictionaryFields.CreatedBy == userAccount);
                    userWordList.PredicateExpression.Add(DictionaryFields.Merged == false);
                    wordList.RemovedEntitiesTracker = deletedWords;
                    adaptor.FetchEntityCollection(wordList, userWordList);
                    PersistToLocalStorage();
                    userDictionarySaved = false;
                }
                catch (Exception e)
                {
                    throw new Exception("Cannot acquire users dictionary for " + userAccount, e);
                }
            }
        }

A user can add and remove words from their user dictionary.

If the delete one or more words, then I update the wordlist entity collection

    public void RemoveDeletedWords(ArrayList userList)
    {
        // removes words deleted from the user dictionary
        bool removedAWord;
        do
        {
            removedAWord = false;
            foreach (DictionaryEntity wordToCheck in wordList)
            {
                if (wordToCheck.Merged) continue; //ignore merged words
                if (WordMissing(userList, wordToCheck.Word))
                {
                    wordList.Remove(wordToCheck);
                    removedAWord = true;
                    break;
                }
            }
        } while (removedAWord);
    }

When I am saving changes made to the user dictionary which can include additions and deletions I use this

        public bool SaveUserDictionary()
        {
            // ensure this is called only once
            if(userDictionarySaved) return true;

            ArrayList fileWordList = new ArrayList();
            LoadWordList(fileWordList);
            AddNewWords(fileWordList);
            RemoveDeletedWords(fileWordList);

            using (var adaptor = new DataAccessAdapter(connection_String))
            {
                adaptor.StartTransaction(IsolationLevel.ReadCommitted, "Dictionary");
                try
                {
                    if(wordList.Count > 0)
                        adaptor.SaveEntityCollection(wordList);
                    if (deletedWords.Count > 0)
                        adaptor.DeleteEntityCollection(deletedWords);
                    adaptor.Commit();
                    userDictionarySaved = true;
                    return true;
                }
                catch (ORMConcurrencyException)
                {
                    // someone else has updated the same record as us.
                    // or some one has deleted one that we have deleted or updated.
                    return false;
                }
                catch (Exception e)
                {
                    // We have an error, reverse any changes we have made
                    adaptor.Rollback();
                    throw new Exception("User dictionary update error for " + user_Account, e);
                }
            }
        }

I have removed a word, it is moved into the deletedWords collection but I get a null exception on adaptor.DeleteEntityCollection(deletedWords); in DataAccessAdapter.cs here

                case PredicateType.FieldCompareValuePredicate:
                    FieldCompareValuePredicate compareValuePredicate = (FieldCompareValuePredicate)currentPredicate;
                    if(compareValuePredicate.PersistenceInfo==null)
                    {
                        compareValuePredicate.PersistenceInfo = GetFieldPersistenceInfo((IEntityField2)compareValuePredicate.FieldCore);
                    }
                    break;

Any ideas what is going wrong. I have used similar logic elsewhere and I don't remember having any problems before

Heres details of the exception

System.NullReferenceException was unhandled by user code
  Message="Object reference not set to an instance of an object."
  Source="SD.LLBLGen.Pro.ORMSupportClasses.NET20"
  StackTrace:
       at SD.LLBLGen.Pro.ORMSupportClasses.EntityFieldCore.get_ContainingObjectName()
       at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.GetFieldPersistenceInfo(IEntityField2 field)
       at PathWest.DataAccess.Dictionary.DatabaseSpecific.DataAccessAdapter.InsertPersistenceInfoObjects(IPredicateExpression expression) in C:\ProjectsUncontrolled\MessageOfTheDay\Dictionary DAL\DatabaseSpecific\DataAccessAdapter.cs:line 378
       at PathWest.DataAccess.Dictionary.DatabaseSpecific.DataAccessAdapter.InsertPersistenceInfoObjects(IPredicateExpression expression) in C:\ProjectsUncontrolled\MessageOfTheDay\Dictionary DAL\DatabaseSpecific\DataAccessAdapter.cs:line 350
       at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.DeleteEntity(IEntity2 entityToDelete, IPredicateExpression deleteRestriction)
       at SD.LLBLGen.Pro.ORMSupportClasses.UnitOfWork2.Commit(IDataAccessAdapter adapterToUse, Boolean autoCommit)
  InnerException: 

cry cry cry cry cry cry cry cry cry

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 27-Nov-2009 10:43:27   

at SD.LLBLGen.Pro.ORMSupportClasses.UnitOfWork2.Commit(IDataAccessAdapter adapterToUse, Boolean autoCommit)

Are you using a UnitOfWork, somewhere?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 29-Nov-2009 12:58:36   

Runtime lib build nr etc. ?

it looks like a field doesn't get its persistence info injected so we need the rtl lib to know if it's an old build or not. This error could also be caused by user error in your code, but let's first check whether the latest runtime build fixes the issue or not?

Frans Bouma | Lead developer LLBLGen Pro
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 00:46:19   

Otis wrote:

Runtime lib build nr etc. ?

it looks like a field doesn't get its persistence info injected so we need the rtl lib to know if it's an old build or not. This error could also be caused by user error in your code, but let's first check whether the latest runtime build fixes the issue or not?

My understanding is that I am using ther latest build.

According to the about form - Version 2.6 Final, Realeased on October 9th, 2009.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 00:55:22   

Looked at the assembly itself

C:\Program Files\Solutions Design\LLBLGen Pro v2.6\RuntimeLibraries\DotNET20\SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll

Assembly Version 2.6.9.1005

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 00:59:38   

Here is a trace of whats happening

Method Exit: DataAccessAdapterBase.ExecuteMultiRowRetrievalQuery
Method Exit: DataAccessAdapterBase.FetchEntityCollectionInternal(7)
Method Enter: DataAccessAdapterBase.CloseConnection
Method Exit: DataAccessAdapterBase.CloseConnection
Method Exit: DataAccessAdapterBase.FetchEntityCollection(sunglasses
MainWorkItem OnActivated
MessageView OnButtonToolClick
Before: OnClose - SmartPart=Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
After: OnClose - SmartPart=Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
Before: OnClose - SmartPart=Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
After: OnClose - SmartPart=Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
Before: OnClose - SmartPart=Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
After: OnClose - SmartPart=Microsoft.Practices.CompositeUI.WinForms.DeckWorkspace
MainWorkItem OnActivated
MainWorkItem OnTearingDown
Method Enter: DataAccessAdapterBase.StartTransaction
Transaction name: Dictionary. Isolation level: ReadCommitted. Method Enter: DataAccessAdapterBase.OpenConnection
New connection created.

Connection physically opened. Method Exit: DataAccessAdapterBase.OpenConnection Method Exit: DataAccessAdapterBase.StartTransaction Method Enter: DataAccessAdapterBase.SaveEntityCollection(3) Active Entity Collection Description: EntityCollection: PathWest.DataAccess.Dictionary.HelperClasses.EntityCollection. Will contain entities of type: DictionaryEntity

Method Enter: UnitOfWork2.Commit(2)
Transaction to use: Dictionary. AutoCommit: False
Handling Pre Insert CallBacks.

Handle Inserts. Method Enter: DataAccessAdapterBase.PersistQueue Persistence action info: Action: Insert. Queue length: 1 Current persisted entity info: Entity: PathWest.DataAccess.Dictionary.EntityClasses.DictionaryEntity. ObjectID: ffcf5aaa-588b-4dd1-9a9e-015451e63ff4 PrimaryKey field: DictionaryId. Type: System.Int32. Value: <undefined value> Method Enter: DataAccessAdapterBase.ExecuteActionQuery Method Enter: DataAccessAdapterBase.OpenConnection Method Exit: DataAccessAdapterBase.OpenConnection Method Enter: Query.ReflectOutputValuesInRelatedFields

Syncing field DictionaryId with parameter @DictionaryId. Method Exit: Query.ReflectOutputValuesInRelatedFields Executed Sql Query: Query: INSERT INTO [WardenII].[Global].[Dictionary] ([Word], [Merged]) VALUES (@Word, @Merged);SELECT @DictionaryId=SCOPE_IDENTITY() Parameter: @DictionaryId : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Output. Value: 276. Parameter: @Word : String. Length: 50. Precision: 0. Scale: 0. Direction: Input. Value: "Chucken". Parameter: @Merged : Boolean. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: False.

Method Exit: DataAccessAdapterBase.ExecuteActionQuery
PersistQueue method result: queuePersisted result: True
Method Exit: DataAccessAdapterBase.PersistQueue
Handling Pre Update CallBacks.
Handle Updates. Method Enter: DataAccessAdapterBase.PersistQueue Persistence action info: Action: Update. Queue length: 0 PersistQueue method result: queuePersisted result: True Method Exit: DataAccessAdapterBase.PersistQueue
Handling UpdateEntitiesDirectly Calls.
Handling Pre Delete CallBacks.
Handle Deletes.
Handling Post Delete CallBacks.

Handling DeleteEntitiesDirectly Calls. Method Enter: UnitOfWork2.Reset Method Exit: UnitOfWork2.Reset Method Exit: UnitOfWork2.Commit(2) Method Exit: DataAccessAdapterBase.SaveEntityCollection(3) Method Enter: DataAccessAdapterBase.DeleteEntityCollection Active Entity Collection Description: EntityCollection: PathWest.DataAccess.Dictionary.HelperClasses.EntityCollection. Will contain entities of type: DictionaryEntity

Method Enter: UnitOfWork2.Commit(2)
Transaction to use: Dictionary. AutoCommit: False
Handling Pre Insert CallBacks.
Handle Inserts. Method Enter: DataAccessAdapterBase.PersistQueue Persistence action info: Action: Insert. Queue length: 0 PersistQueue method result: queuePersisted result: True Method Exit: DataAccessAdapterBase.PersistQueue
Handling Pre Update CallBacks.
Handle Updates. Method Enter: DataAccessAdapterBase.PersistQueue Persistence action info: Action: Update. Queue length: 0 PersistQueue method result: queuePersisted result: True Method Exit: DataAccessAdapterBase.PersistQueue
Handling UpdateEntitiesDirectly Calls.
Handling Pre Delete CallBacks.

Handle Deletes. Method Enter: DataAccessAdapterBase.DeleteEntity(2) Active Entity Description: Entity: PathWest.DataAccess.Dictionary.EntityClasses.DictionaryEntity. ObjectID: f5e7f54f-24cd-4c3e-8a9a-8d1bc9410317 PrimaryKey field: DictionaryId. Type: System.Int32. Value: 272

A first chance exception of type 'System.NullReferenceException' occurred in SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 01:03:08   

Here is a definition of the table


CREATE TABLE [Global].[Dictionary](
    [DictionaryId] [int] IDENTITY(1,1) NOT NULL,
    [Word] [nvarchar](50) NOT NULL,
    [Merged] [bit] NOT NULL,
    [Concurrency] [timestamp] NOT NULL,
    [CreatedBy] [nvarchar](30) NOT NULL,
    [DateCreated] [date] NOT NULL,
    [TimeCreated] [datetime] NOT NULL,
    [UpdatedBy] [nvarchar](30) NULL,
    [DateUpdated] [date] NULL,
    [TimeUpdated] [datetime] NULL,
 CONSTRAINT [PK_Dictionary] PRIMARY KEY CLUSTERED 
(
    [DictionaryId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Every table has these same 7 fields

    [Concurrency] [timestamp] NOT NULL,
    [CreatedBy] [nvarchar](30) NOT NULL,
    [DateCreated] [date] NOT NULL,
    [TimeCreated] [datetime] NOT NULL,
    [UpdatedBy] [nvarchar](30) NULL,
    [DateUpdated] [date] NULL,
    [TimeUpdated] [datetime] NULL,

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 01:20:14   

I remembered I had changed the collation of [Word] nvarchar NOT NULL to make it case senstive.

I refreshed the catalog, then ran the generator and replaced the class libraries.

VS2008 reloaded them. Cleaned and Rebuilt the solution. Ran the application

used test words as per:- added a word - Chucken for insertion deleted the word - HokeyPokey

The logic only inserts new words and deletes existing ones. The insert works fine (path of least resistance I guess). The delete does not.

I did check the deleted entities collection with the debugger, it does contain one entity so that parts working.

I might remove the ConcurrencyPredicate for the delete and see if that works.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 01:26:29   

Removed the concurrencypredicates and it works fine.

Kinda worries me for later on though. confused

An insert does not need one. wink It does not matter in this instance that a dictionary entry has been deleted within another transaction but in other cases it might. disappointed

What annoys me is that I am certain I used the same logic previously (it was with an older build of LLBLGen Pro) and it worked fine. frowning

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 30-Nov-2009 09:17:12   

public class GenericConcurrencyFilterFactory : IConcurrencyPredicateFactory { public IPredicateExpression CreatePredicate( ConcurrencyPredicateType predicateTypeToCreate, object containingEntity) { var entity = (EntityBase2)containingEntity;

        var timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

        IPredicateExpression expression = new PredicateExpression();

        switch (predicateTypeToCreate)
        {
            case ConcurrencyPredicateType.Save:
            case ConcurrencyPredicateType.Delete:
                expression.Add(timestampField == entity.Fields["Concurrency"].DbValue);
                break;
        }
        return expression;
    }
}

Please post the DependencyInjectionInfo attribute decorating the above class. Try explicit type assignment, if it may help:

EntityBase2entity = (EntityBase2)containingEntity;
EntityField2timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

If not then maybe you can do something like:

expression.Add((EntityField2)entity.Fields["Concurrency"] == entity.Fields["Concurrency"].DbValue);
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 09:29:32   

Here is the complete source (except the using statements)

namespace PathWest.Common.BusinessEntities { [DependencyInjectionInfo(typeof(IEntity2), "GenericConcurrencyFilterFactory", ContextType = DependencyInjectionContextType.NewInstancePerTarget)] [Serializable] public class GenericConcurrencyFilterFactory : IConcurrencyPredicateFactory { public IPredicateExpression CreatePredicate( ConcurrencyPredicateType predicateTypeToCreate, object containingEntity) { var entity = (EntityBase2)containingEntity;

        var timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

        IPredicateExpression expression = new PredicateExpression();

        switch (predicateTypeToCreate)
        {
            case ConcurrencyPredicateType.Save:
            case ConcurrencyPredicateType.Delete:
                expression.Add(timestampField == entity.Fields["Concurrency"].DbValue);
                break;
        }
        return expression;
    }
}

}

I did not think the attributes were really necessay unless automatic dependancy injection was going to be used.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 09:37:51   

Try explicit type assignment, if it may help: Code:

EntityBase2entity = (EntityBase2)containingEntity;
EntityField2timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

If not then maybe you can do something like: Code:

expression.Add((EntityField2)entity.Fields["Concurrency"] == entity.Fields["Concurrency"].DbValue);

Where exactly am I supposed to try this. In the ConcurrencyPredicateFactory or where I instantiate the entity collections?

Sorry I am a bit confused.

I am sure that logic has worked in the past. disappointed The null exception caught me by surprise.frowning

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 30-Nov-2009 09:43:23   

In the concurrency Predicate class.

[DependencyInjectionInfo(typeof(IEntity2), "GenericConcurrencyFilterFactory", ContextType = DependencyInjectionContextType.NewInstancePerTarget)]

Also you should try replacing the IEntity2 with EntityBase2 in the DependencyInjectionInfo attribute.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 09:45:17   

Just had a look at my ConcurrencyPredicateFactory (Actually more less cloned from one of your examples).

Code:

EntityBase2entity = (EntityBase2)containingEntity;
EntityField2timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

I am already doing this

public class GenericConcurrencyFilterFactory : IConcurrencyPredicateFactory { public IPredicateExpression CreatePredicate( ConcurrencyPredicateType predicateTypeToCreate, object containingEntity) { var entity = (EntityBase2)containingEntity;

        var timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

        IPredicateExpression expression = new PredicateExpression();

        switch (predicateTypeToCreate)
        {
            case ConcurrencyPredicateType.Save:
            case ConcurrencyPredicateType.Delete:
                expression.Add(timestampField == entity.Fields["Concurrency"].DbValue);
                break;
        }
        return expression;
    }
}

I am not sure how to implement the following

expression.Add((EntityField2)entity.Fields["Concurrency"] == entity.Fields["Concurrency"].DbValue);

Any pointers?

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 09:47:34   

Must be blind as well as stupid

Am also doing this

expression.Add((EntityField2)entity.Fields["Concurrency"] == entity.Fields["Concurrency"].DbValue);

public class GenericConcurrencyFilterFactory : IConcurrencyPredicateFactory
{
    public IPredicateExpression CreatePredicate(
        ConcurrencyPredicateType predicateTypeToCreate,
        object containingEntity)
    {
        var entity = (EntityBase2)containingEntity;

        var timestampField = (EntityField2)EntityFieldFactory.Create(entity.GetType().Name, "Concurrency");

        IPredicateExpression expression = new PredicateExpression();

        switch (predicateTypeToCreate)
        {
            case ConcurrencyPredicateType.Save:
            case ConcurrencyPredicateType.Delete:
                expression.Add(timestampField == entity.Fields["Concurrency"].DbValue);
                break;
        }
        return expression;
    }
}
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 09:53:26   

Ok changed the attribute to
[DependencyInjectionInfo(typeof(EntityBase2), "GenericConcurrencyFilterFactory", ContextType = DependencyInjectionContextType.NewInstancePerTarget)] [Serializable] public class GenericConcurrencyFilterFactory : IConcurrencyPredicateFactory {

Still getting a null exception at the red linecry

                case PredicateType.FieldCompareValuePredicate:
                    FieldCompareValuePredicate compareValuePredicate = (FieldCompareValuePredicate)currentPredicate;
                    if(compareValuePredicate.PersistenceInfo==null)
                    {

** compareValuePredicate.PersistenceInfo = GetFieldPersistenceInfo((IEntityField2)compareValuePredicate.FieldCore);** } break;

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 30-Nov-2009 10:00:21   

I could use the deleted entity collection with a grid to see what it contains.

Maybe, its a only small possibility, but the could the RemovedEntitiesTracker collection not be getting a complete copy of each entity that is deleted (or removed).

I will have a look tomorrow. Its time to go home for me.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 01-Dec-2009 02:29:25   

I created a new form just to hold two grids to display the two entity collections.

See attachment

The top grid displays the Dictionary entity collection after two new entities have been added and two entities have been removed.

The bottom is a grid that displays the contents of the RemovedEntitiesTracker entity collection. This contains the two entites removed from Dictionary Entity Collection.

From what I can observe this is behaving 100% as expected.

Its only when the statement in red is executed that the null exception occurs

** if (deletedWords.Count > 0) adaptor.DeleteEntityCollection(deletedWords);**

using (var adaptor = new DataAccessAdapter(connection_String))
            {
                adaptor.StartTransaction(IsolationLevel.ReadCommitted, "Dictionary");
                try
                {
                    if(wordList.Count > 0)
                        adaptor.SaveEntityCollection(wordList);
                    if (deletedWords.Count > 0)
                        adaptor.DeleteEntityCollection(deletedWords);
                    adaptor.Commit();
                    userDictionarySaved = true;
                    return true;
                }
                catch (ORMConcurrencyException)
                {
                    // someone else has updated the same record as us.
                    // or some one has deleted one that we have deleted or updated.
                    return false;
                }
                catch (Exception e)
                {
                    // We have an error, reverse any changes we have made
                    adaptor.Rollback();
                    throw new Exception("User dictionary update error for " + user_Account, e);
                }
            }

** As far as I can tell it should work but it is not.**rage

What else can I check?confused

Attachments
Filename File size Added on Approval
entities.zip 16,018 01-Dec-2009 02:29.47 Approved
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 01-Dec-2009 09:13:06   

Ah multiple expletives and many nasty bad words. rage I thought I would try something smart but found it cost me a lot of time.

flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed flushed

Virtually every application we will be writing will be using the dictionary code that I have written in a separate class library.

So I thought, why not generate a set of LLBLGen Pro classes just for the tables and stored procs for handling dictionary stuff.

Then for database access to handle other tables, views etc create a second set of LLBLGen Pro classes.

Give each set of projects (generic and database specific) a different name space.

Looked ok, the Build was ok, it ran ok except for when I updated the dictionary tables and used a common concurrencypredicate factory. It then bombed with a null exception.

I discovered the reason why when I was looking at the code and said why not move all my entity collections to generic collections while I am waiting for an update on the forum. While I was doing this I got an ambiguous reference warning (I think it was with EntityCollection<DictionaryEntity>).

That stopped me in my tracks and it sudenly dawned on me that my idea was possibly not quite appropriate.

I excluded the special LLBLGen Pro class library projects built for my dictionary. Ran the LLBLGen Pro generator and included the required tables and stored procs for the dictionary. Cleaned up the code and rebuilt everything.

It worked just fine.flushed

**Lesson learn. **If I want to do this I will need a more sophisticated approach like creating a separate domain assembly and then load it into my application domain when I need to use it. simple_smile

I am sorry if you put too much effort into helping me in solving this self inflicted debacle.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 01-Dec-2009 09:39:10   

Glad you have found it. Another possible solution would be to use full qualified names for each object you create. (e.g DataAccessAdapter, EntityCollection<T>...etc) to avoid ambiguity.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 01-Dec-2009 09:51:08   

Thanks for the suggestion.

I had started doing that but there was so much re-work to do and with me the chances of making a mistake would be fairly high. Any such mistake would result in another difficult to track down error.

It was easier to collapse everything into the two class libraries and let the IDE tell me where I needed to fix things.

sunglasses