2009-09-01 9 views
5

Estoy tratando de averiguar cómo mapear una propiedad IDictionary en 1.0 con fluidez.Código fluido para mapear un IDictionary <SomeEntity, int>?

Según mi entender, esto se traduce en una asociación ternaria.

Ejemplo:

class Bar 
{ 
    public IDictionary<SomeEntity, int> Foo {get; set;} 
} 

Bar.hbm.xml contendría entonces:

<map name="Foo" table="BarFooTable"> 
    <key column="..."/> 
    <index-many-to-many class="SomeEntity" column="SomeEntity_Id"/> 
    <element column="Value" type="int"/> 
</map> 

¿Qué tendría que escribir en nhibernate fluidez para producir este mapeo XML?

El punto de interés aquí es que la clave es un tipo de entidad mientras que el valor es un tipo de valor. (Editar: Al menos, esto parece distinguirse de los otros ejemplos y preguntas que flotan en stackoverflow o grupos de google, que son value-value o key-key)

Después de mucha experimentación, puedo producir una asignación para un IDictionary<SomeEntity,SomeEntity> tipos de entidad (puro):

HasManyToMany(x => x.Foo) 
     .AsMap("Key") 
     .AsTernaryAssociation("Key2", "Value") 
     ; 

también puedo producir una asignación para un (tipos de valor puro) IDictionary<int,int>:

HasMany(x => x.Foo) 
    .AsMap<int>("Key") 
    .Element("Value") 
    ; 

que puede incluso conseguir alguna manera de producir una asignación para un IDictionary<int, SomeValue), aunque ninguno que NHibernate aceptará.

Pero no puedo entender cómo producir un mapeo para un IDictionary<SomeValue, int> que es lo que quiero. ¿Alguien puede dar algunos consejos?

+0

crossposted a http://groups.google.com/group/fluent-nhibernate/browse_thread/thread/b1b335ff5f9a6a40 – fostandy

Respuesta

1

me encontré con el mismo problema, y ​​wasn' t feliz con la mezcla de fluidez y mapeos hbm. Puedes ver mi corrección here.

0

Parece que tenemos el mismo problema:

How to map this in Fluent.NHibernate

acabo hbm.xml utilizado (que fue generado por Fluent.Nhibernate en mi proyecto) he modificado un poco oufcourse. Si establece

.Mappings(m => 
    {            
     m.FluentMappings.AddFromAssemblyOf<DomainClass>() 
         .ExportTo("Path"); 
     m.HbmMappings.AddFromAssemblyOf<DomainClass>(); 
    }) 

y si tiene tanto ClassMap y hbm.xml la hbm.xml debe pasar por encima del ClassMap, por lo que será bien hasta que ha fijado.

también necesidad natural-id para mi clase y también no es compatible con Fluent.Nhibernate, así que no tuve más remedio que utilizar hbm.xml

+0

Sí, esto es actualmente la manera que soy haciendo las cosas bien. Lamentablemente, tengo una clase bastante pesada que, si bien tiene muchas propiedades que se pueden asignar con fluidez, también tiene IDictionary . Mi 'solución' hasta ahora ha sido separar la funcionalidad en clases separadas (una mapeada fluidamente, una a través de hbm.xml sin procesar) y usar una asignación de uno a uno, pero por razones de rendimiento ahora es deseable eliminar la unión/selección extra que se produce a partir de esto. (ver http://groups.google.com/group/fluent-nhibernate/browse_frm/thread/b5fe376e257436e9/35d9cf5cef4303d0) – fostandy

2
HasMany(x => x.Foo) 
    .KeyColumn("BarId") 
    .Element("IntValue") 
    .AsMap<SomeEntity>("SomeEntityId") 
    .AsTernaryAssociation("SomeEntityId"); 
+0

Acabo de tener el mismo problema, basado en su solución Terminé con 'HasManyToMany (x => x. colección) \t \t \t \t .ParentKeyColumn ("parentid") \t \t \t \t .ChildKeyColumn ("childid") \t \t \t \t .AsMap ("childid"). Elemento ("Valor", p => p .Columna ("Valor"). Tipo ()) \t \t \t \t .AsTernaryAssociation ("childid", "Valor") \t \t \t \t \t \t \t \t .Tabla ("Relationstable"); ' –

0

Dadas estas clases (simplificado):

class LetterTemplate 
{ 
    IDictionary<State, FieldAccessOptionality> StateAccess {get; protected set;} 
} 

class State 
{ 
} 

enum FieldAccessOptionality 
{ 
} 

Esto funcionó para mí.

(Sí, sé que el valor es un Enum, pero el principio es el mismo que un int).

HasManyToMany(x => x.StateAccess) 
    .ParentKeyColumn("`letter_template`") 
    .ChildKeyColumn("`state`") 
    .AsMap<State>("`state`") 
    .Element("`access`", 
     p => 
     p.Type<IntEnumType<FieldAccessOptionality>>()) 
    .AsTernaryAssociation("`state`", "`access`") 
    .Table("`letter_template_state_access`"); 

Nota del IntEnumType <> clase que se convierte de una enumeración a un int para NHibernate. Si estuviera mapeando un int en lugar de una enumeración, podría usar el NHibernate Int32Type IUserType estándar. La lista completa de esta clase es el siguiente:

public class IntEnumType<T> : IUserType where T : struct 
{ 
    public object Assemble(object cached, object owner) 
    { 
    return cached; 
    } 

    public object DeepCopy(object value) 
    { 
    return value; 
    } 

    public object Disassemble(object value) 
    { 
    return value; 
    } 

    public new bool Equals(object a, object b) 
    { 
    return Object.Equals(a, b); 
    } 

    public int GetHashCode(object x) 
    { 
    if (x == null) 
     return 0; 
    else 
     return x.GetHashCode(); 
    } 

    public bool IsMutable 
    { 
    get { return false; } 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
    object result = NHibernateUtil.Int32.NullSafeGet(rs, names); 
    if (result == null) 
    { 
     return null; 
    } 
    else 
    { 
     Type typ = Enum.GetUnderlyingType(typeof(T)); 
     result = Convert.ChangeType(result, typ); 
     return Enum.ToObject(typeof(T), result); 
    } 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
    if (value == null) 
     ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; 
    else 
     ((IDataParameter)cmd.Parameters[index]).Value = Convert.ChangeType(value, typeof(int)); 
    } 

    public object Replace(object original, object target, object owner) 
    { 
    return original; 
    } 

    public Type ReturnedType 
    { 
    get { return typeof(T); } 
    } 

    public SqlType[] SqlTypes 
    { 
    get 
    { 
     SqlType type = new SqlType(DbType.Int32); 
     return new SqlType[] { type }; 
    } 
    } 

} 
Cuestiones relacionadas