2010-03-12 11 views
0

J'essaie d'utiliser la fonctionnalité automap pour générer un DDL pour le modèle et le programme suivants, mais je reçois toujours l'erreur . Classe non mappée: IRole "lorsque j'appelle la méthode GenerateSchemaCreationScript dans NHibernate. Quand je remplace le type des ILists avec l'implémentation des interfaces (User et Role) tout fonctionne bien. Qu'est-ce que je fais mal ici? Comment puis-je utiliser couramment les versions implémentées de IUser et IRole telles que définies dans dans Unity?Erreur lors de l'utilisation des interfaces dans le modèle

public interface IRole 
{ 
    string Title { get; set; } 
    IList<IUser> Users { get; set; } 
} 

    public interface IUser 
    { 
     string Email { get; set; } 
     IList<IRole> Roles { get; set; } 
    } 

public class Role : IRole 
{ 
    public virtual string Title { get; set; } 
    public virtual IList<IUser> Users { get; set; } 
} 
public class User : IUser 
{ 
    public virtual string Email { get; set; } 
    public virtual IList<IRole> Roles { get; set; } 
} 

J'utilise le programme suivant pour générer le DDL à l'aide du GenerateSchemaCreationScript dans NHibernate:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var ddl = new NHibernateSessionManager(); 
     ddl.BuildConfiguration(); 
    } 
} 

    public class NHibernateSessionManager 
    { 
     private ISessionFactory _sessionFactory; 
     private static IUnityContainer _container; 

     private static void InitContainer() 
     { 
      _container = new UnityContainer(); 
      _container.RegisterType(typeof(IUser), typeof(User)); 
      _container.RegisterType(typeof(IRole), typeof(Role)); 
     } 

     public ISessionFactory BuildConfiguration() 
     { 
      InitContainer(); 
      return 
Fluently.Configure().Database(MsSqlConfiguration.MsSql2008 
       .ConnectionString("ConnectionString")) 
       .Mappings(m => m.AutoMappings.Add(
        AutoMap.AssemblyOf<IUser>())) 
       .ExposeConfiguration(BuildSchema) 
       .BuildSessionFactory(); 
     } 

     private void BuildSchema(Configuration cfg) 
     { 
      var ddl = cfg.GenerateSchemaCreationScript(new 
NHibernate.Dialect.MsSql2008Dialect()); 
      System.IO.File.WriteAllLines("Filename", ddl); 
     } 

    } 

Répondre

0

Vous ne pouvez pas fournir une interface que le type T AssemblyOf<T>, vous devez fournir un béton type. Ou vous pouvez utiliser la méthode qui accepte un assemply:

.Mappings(m => m.AutoMappings.Add(
       AutoMap.Assembly(myAssembly))) 

Edit: Le problème est que vos classes contiennent des collections de types d'interface au lieu de type de classe. Je ne sais pas s'il est possible d'automatiser les interfaces de cette manière. En outre, je pense qu'il est rarement utile d'utiliser des interfaces pour spécifier des objets de domaine.

+0

Désolé à ce sujet - Il faut bien sûr: .Mappings (m = > m.AutoMappings.Add ( AutoMap.AssemblyOf ())) Mais mon problème est toujours le même, je reçois des erreurs sur: public virtual IList Utilisateurs {get; ensemble; } et public virtual IList Rôles {get; ensemble; } Des idées pour résoudre ce problème? – Bjarke

+0

Voir le montage de ma réponse originale. –

+0

Selon http://steve-fair-dev.blogspot.com/2009/10/nhibernate-entity-property-is-interface.html, il est possible de dire à NHibernate quelle implémentation il doit utiliser pour une interface (en utilisant des dossiers). Je me demande simplement s'il existe un moyen de laisser le savoir-faire de Fluent savoir la même chose? – Bjarke

1

Je suis dans la même situation que vous. Après avoir utilisé ClassMap avant de savoir que vous pouvez le faire avec Fluent, je n'avais jamais utilisé la fonction AutoMapping auparavant. J'ai réussi à faire un mappage un à un avec AutoMapper en utilisant un IReferenceConvention (voir précédent SO post).

J'ai maintenant rencontré le même problème que vous où j'ai un mappage un à plusieurs avec lequel j'ai maintenant un problème. Il y a une interface IHasManyConvention que j'ai commencé à regarder mais qui n'a pas eu de chance pour le moment. Tout simplement parce que quelque chose est difficile à faire, cela ne le trompe pas, le mappage vers les interfaces a une valeur défiante et peut facilement être effectué dans les fichiers de mappage raw nHibernate ou en utilisant des fichiers de mappage Fluents ClassMap. Je pense qu'une fois que les gens commenceront à faire plus avec la fonctionnalité AutoMapping, il y aura plus de billets de blog.

EDIT

J'ai trouvé une solution intermédiaire à l'aide d'un IAutoMappingOverride. Voici un exemple approximatif de ce dont vous avez besoin.

public class RoleAutoMappingOverride : IAutoMappingOverride<Role> 
{ 
    public void Override(AutoMapping<Role> mapping) 
    { 
     mapping.HasMany<User>(x => x.Users).KeyColumn("User_id"); 
    } 
} 

EDIT

Un collège de mes a élaboré une meilleure solution qui utilise des conventions au lieu de la dérogation. Cela couvre la façon de faire une seule classe, mais si vous regardez le poste de SO que j'ai mentionné avant, vous pouvez voir comment cela pourrait être fait générique.

public class Foo : IHasManyConvention 
{ 
    public void Apply(IOneToManyCollectionInstance instance) 
    { 
     if (instance.ChildType == typeof(Role)) 
     { 
      instance.Relationship.CustomClass<User>(); 
     } 
    } 
} 

EDIT

J'ai maintenant tourné cela et mon autre post dans un billet de blog: http://bronumski.blogspot.com/2011/01/making-fluent-nhibernate-automapper.html