New Posts New Posts RSS Feed: Type conflict
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Type conflict

 Post Reply Post Reply
Author
Sinnema View Drop Down
Groupie
Groupie
Avatar

Joined: 23-Mar-2009
Location: Muri AG, EU, CH
Posts: 54
Post Options Post Options   Quote Sinnema Quote  Post ReplyReply Direct Link To This Post Topic: Type conflict
    Posted: 29-Jul-2009 at 9:23am
Hi,
 
Our development, at this moment, is realy going well. DevForce Winclient is in development a real pleasure to work with.
 
Today we had to deploy our first result and we ran into a snag. We don't understand the message we're getting.
 
We tried to deploy a client and server using the N-Tier Configuration Starter tool. The tool work fine (I think) but the result was not satisfying. The server starts without problems but the Client get's an error:
Type conflict:  the DefaultManager is currently of type EntityManager
Who can tell us what this means?
 
Regards,
Paul Sinnema
Diartis AG
Back to Top
GregD View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 374
Post Options Post Options   Quote GregD Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jul-2009 at 10:27am
The Object Mapper generates a subclassed EntityManager, named DomainModelEntityManager by default. The subclassed EntityManager includes methods that return queries specific to your domain model, etc.

Whatever flavor of EntityManager you instantiate first (subclassed or otherwise) becomes the one assigned to DefaultManager. Thus, if you instantiate an EntityManager at startup:

    EntityManager foo = new EntityManager();

that becomes the DefaultManager. Then if you later try to do something that needs the DefaultManager to be the subclassed version (DomainModelEntityManager), you'll get a type conflict.  Very likely you've got something like that going on.
Back to Top
Sinnema View Drop Down
Groupie
Groupie
Avatar

Joined: 23-Mar-2009
Location: Muri AG, EU, CH
Posts: 54
Post Options Post Options   Quote Sinnema Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jul-2009 at 11:10am
Hi Greg,
 
Thanks for the reply.
 
Whell I can tell you we're not instantiating any EntityManager ourselves anywhere in the code. We use the DefaultManager solely (at the moment). So far we do not intend to do otherwise, but one can never say 'never' for sure.
 
Having said that, it seems peculiar what happens here. We could deduce that the server somehow launches a different flavor of the EntityManager, causing the Type conflict. But I would like to hear from you what you think is going on.
 
Regards,
Paul Sinnema
Diartis AG
 
Back to Top
skingaby View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 23-Apr-2008
Location: United States
Posts: 146
Post Options Post Options   Quote skingaby Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jul-2009 at 12:26pm
The DefaultManager property will automatically create an EntityManager, which you don't want. You will need to create a DomainModelEntityManager and use that. For the server-side, this can be handled in the global.asax:

protected void Application_Start(Object sender, EventArgs e)

{
     IdeaBlade.Core.IdeaBladeConfig.AssertNonDefaultVersion();
     ConfigureEntityManager();
}

private void ConfigureEntityManager()
{
     DomainModel.Utility.LocalEntityManager.DefaultManager = new DomainModel.DomainModelEntityManager();
     DomainModel.Utility.LocalEntityManager.DefaultManager.LoginAsync(null, args => LoginCallback(args, null), null);
}

private void LoginCallback(IdeaBlade.EntityModel.LoginEventArgs args, Action callback)
{
     if (args.Error != null)
          throw args.Error;
}


For the client-side, in a Silverlight App, the Prism Explorer shows this being initialized in each module's PersistenceService by overriding the CreateEntityManagerCore() method.
protected override IdeaBlade.EntityModel.EntityManager CreateEntityManagerCore()

{
     var em = new DomainModelEntityManager();
     LocalEntityManager.DefaultManager = em;
     var task = AsyncSerialTask.Create();
     var task1 = task.AddAsyncLogin(em, new LoginCredential(null, null, null));
     task1.AddExceptionHandler(CreateEntityManagerCoreAsyncSerialTaskExceptionHandler);
     var task2 = task1.AddAsyncAction<AsyncEventArgs>((loginEventArgs, callback) =>          
          LocalEntityManager.InitializeCacheAsync(callback,
          Tools.AsyncSerialTaskParallelCallback));
     task2.AddExceptionHandler(CreateEntityManagerCoreAsyncSerialTaskExceptionHandler);
     task2.Execute(null, args => CreateEntityManagerCoreCallback(args));
     return em;
}

public void CreateEntityManagerCoreCallback(AsyncSerialTaskCompletedArgs<AsyncEventArgs> args)
{
     //TODO: Do something cool here. Like raise an event back to the VM to tell it we're done initializing the EM/cache.
}

public static void CreateEntityManagerCoreAsyncSerialTaskExceptionHandler(AsyncSerialTaskExceptionArgs args)
{
     //TODO: This should do something much wiser, like
     //log the error and set an "Error" property
     throw args.Exception;
}


In the above code, you'll notice the LocalEntityManager.DefaultManager. LocalEntityManager is a class we are using to make the EntityManager available to all our domain classes, and it looks like this:
public static class LocalEntityManager

{

     private static DomainModelEntityManager _defaultManager;

     public static DomainModelEntityManager DefaultManager
     {
          get
          {
               return _defaultManager;
          }
          set
          {
               _defaultManager = value;
               _defaultManager.Saving += new EventHandler<IdeaBlade.EntityModel.EntitySavingEventArgs>(_defaultManager_Saving);
          }
     }

     public static void _defaultManager_Saving(object sender, IdeaBlade.EntityModel.EntitySavingEventArgs e)
     {
          VerifierResultCollection allResults = new VerifierResultCollection();
          foreach (Entity item in e.Entities)
          {
               var itemResults = ((BaseEntity)item).VerifyInstance();
               foreach (var result in itemResults) { allResults.Add(result); }
          }
          if (!allResults.AreOk)
          {
               e.Cancel = true;
               VerifierResults = allResults;
               string msg = String.Empty;
               foreach (var result in allResults)
               {
                    if (result.IsError)
                    {
                         if (!String.IsNullOrEmpty(msg))
                              msg += ", ";
                         msg += result.Description;
                    }
               }
               throw new VerifierException("Verifier Failure: " + msg);
          }
     }

     public static VerifierResultCollection VerifierResults { get; set; }

     #region InitializeCache

     public static void InitializeCache()
     {
          var queries = GetInitializationQueries();
          foreach (var item in queries)
          {
               _defaultManager.ExecuteQuery(item);
          }
     }

     /// <summary>
     /// Initialize the EntityManager cache asynchronously. This method should be used
     /// instead of the InitializeCacheAsync(AsyncCompletedCallback<AsyncEventArgs>
     /// serialCallback, Action<AsyncParallelTaskCompletedArgs> completionAction) version.
     /// That one was created to make the Initialize work as part of an AsyncSerialTask.
     /// </summary>
     /// <param name="completionAction">The Action to execute (call back to) to return
     /// the results of this async call.</param>
     public static void InitializeCacheAsync(Action<AsyncParallelTaskCompletedArgs> completionAction)
     {
          InitializeCacheAsync(null, completionAction);
     }

     /// <summary>
     /// Initialize the EntityManager cache asynchronously. This method can be called
     /// inside an AsyncSerialTask because it carries the AsyncSerialTask's callback
     /// through it.
     /// </summary>
     /// <param name="serialCallback">The callback to pass through so the Parallel
     /// completionAction can assemble an AsyncEventArgs toss it over to the Serial
     /// serialCallback.</param>
     /// <param name="completionAction">The Action to execute (call back to) to
     /// return the results of this async call.</param>
     public static void InitializeCacheAsync(AsyncCompletedCallback<AsyncEventArgs> serialCallback, Action<AsyncParallelTaskCompletedArgs> completionAction)
     {
          var task = AsyncParallelTask.Create();
          task.AddExceptionHandler(InitializationExceptionHandler);
          AddInitializationQueries(task);
          task.Execute(serialCallback, completionAction);
     }

     private static void AddInitializationQueries(AsyncParallelTask<object> task)
     {
          var queries = GetInitializationQueries();
          int i = 1;
          foreach (var item in queries)
          {
               IEntityQuery query = item;
               task.AddAsyncAction<EntityFetchedEventArgs>(i, (args, callback) =>
                    _defaultManager.ExecuteQueryAsync(query, callback, null), null);
               i++;
          }
     }

     private static IList<IEntityQuery> GetInitializationQueries()
     {
          var queries = new List<IEntityQuery>();
          queries.Add(_defaultManager.AccountingMonths);
          queries.Add(_defaultManager.DealTypes);

          return queries;
     }

     public static void InitializationExceptionHandler(AsyncParallelTaskExceptionArgs args)
     {
          throw args.Exception;
     }

     #endregion

}
Back to Top
Sinnema View Drop Down
Groupie
Groupie
Avatar

Joined: 23-Mar-2009
Location: Muri AG, EU, CH
Posts: 54
Post Options Post Options   Quote Sinnema Quote  Post ReplyReply Direct Link To This Post Posted: 03-Aug-2009 at 3:06am

Thanks for the info. I'll try it this week.

regards,
Paul Sinnema
Back to Top
Sinnema View Drop Down
Groupie
Groupie
Avatar

Joined: 23-Mar-2009
Location: Muri AG, EU, CH
Posts: 54
Post Options Post Options   Quote Sinnema Quote  Post ReplyReply Direct Link To This Post Posted: 11-Aug-2009 at 9:29am
I've solved this one quite simpeler than SkinGabi suggested. Here's our solution:
 

using Diartis.KLIB.DomainModel;

namespace Diartis.KLIB.KLIBDatabase

{

public static class ModelContext

{

private static KLIBEntityManager m_KLIBEntityManager = null;

/// <summary>

/// This is the main manager for DevForce. It is a singleton pattern that creates a new KLIB Entity Manager

/// </summary>

public static KLIBEntityManager DefaultManager

{

get

{

if (m_KLIBEntityManager == null)

{

m_KLIBEntityManager = new KLIBEntityManager(true);

}

return m_KLIBEntityManager;

}

}

}

}

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down