2012-01-16 22 views
5

Tengo tres clases llamadas Broker, Instrument y BrokerInstrument.Cómo agregar un elemento a un ISet <T>?

using Iesi.Collections.Generic; 

public class Broker : ActiveDefaultEntity 
{ 
    public virtual string Name { get; set; } 
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; } 
} 

public class Instrument : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual string Symbol {get; set;} 
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; } 
    public virtual bool IsActive { get; set; }   
} 

public class BrokerInstrument : Entity 
{ 
    public virtual Broker Broker { get; set; } 
    public virtual Instrument Instrument { get; set; } 
    public virtual decimal MinIncrement { get; set; } 
} 

Si creo tres objetos nuevos (uno de cada tipo) usando esas clases ¿cómo puedo asociarlos? Por ejemplo:

Instrument instrument = new Instrument { 
    Name = "Test Instrument", 
    Symbol = "Test", 
    IsActive = true 
}; 
Broker broker = new Broker { 
    Name = "My Test Broker", 
    IsActive = true, 
    IsDefault = false 
}; 
BrokerInstrument brokerInstrument = new BrokerInstrument { 
    Broker = broker, 
    Instrument = instrument, 
    MinIncrement = 0.01M 
}; 

¿Cómo funciona la instrument "saben" que una nueva brokerInstrument se asocia ahora con ella? Si ahora ejecuto if (instrument.Brokerinstruments == null) obtengo true. ¿Tengo que asociar los objetos en la declaración BrokerInstrument y luego volver y agregarlo al instrument.BrokerInstruments ISet?

Si lo intento hacer: instrument.BrokerInstruments.Add(instrument) me sale un error porque es nulo. Confuso. ¿Qué me estoy perdiendo? ¿Cuál es la mejor manera de modelar relaciones como esta? estos objetos serán persistentes en una base de datos usando NHibernate.

Respuesta

5

Se obtiene una excepción porque no se está inicializando la propiedad BrokerInstruments de la clase de instrumento (es decir, el valor de esa propiedad es null). Para corregir esto, necesita un constructor de instrumentos:

public Instrument() { 
    BrokerInstruments = new HashSet<BrokerInstrument>(); 
} 

Ahora, si quieres que se añade la notificación de un instrumento, eso es un problema diferente. La forma más fácil y más segura es hacer que el BrokerInstruments propiedad getter devuelve un IEnumerable, retire el organismo, y añadir un método AddBrokerInstrument:

// With this, you don't need the constructor above. 
private ISet<BrokerInstrument> _brokerInstruments = new HashSet<BrokerInstrument>(); 

public virtual IEnumerable<BrokerInstrument> BrokerInstruments { 
    get { return _brokerInstruments; } 

    // This setter should allow NHibernate to set the property while still hiding it from external callers 
    protected set { _brokerInstruments = new HashSet<BrokerInstrument>(value); } 
} 

public void AddBrokerInstrument(BrokerInstrument brokerInstrument) { 
    // Any other logic that needs to happen before an instrument is added 
    _brokerInstruments.Add(brokerInstrument); 
    // Any other logic that needs to happen after an instrument is added 
} 

utilizo un IEnumerable anterior porque quiere indicar a los usuarios de esta función que no se les permite agregar instrumentos directamente al conjunto; en su lugar, necesitan llamar a su método.

+0

Parece prometedor, sin embargo cuando ejecuto una prueba de unidad NHibernate se queja con 'TestFixture failed: NHibernate.PropertyNotFoundException: No se pudo encontrar un setter para la propiedad 'BrokerInstruments' en la clase 'MooDB.Domain.Instrument'' ¿Tengo que hacer algo especial en NHibernate ¿ahora? Parece bastante complicado, pero todo lo que quiero hacer es modelar una relación uno-muchos en un modelo de dominio y luego tener NHibernate persistir en los cambios al db. –

+0

Ah, me perdí el bit de NHibernate. Voy a modificar en consecuencia ... Hecho. –

+0

¡Casi! en la línea 'protected set' obtengo un error:' No se puede convertir implícitamente el tipo 'System.Collections.Generic.IEnumerable ' en 'System.Collections.Generic.ISet '. Existe una conversión explícita (¿falta un elenco?) ' –

1

Para poder agregar a una colección, primero debe crear una instancia de la misma. Esto se puede hacer en los respectivos constructores. Mi ejemplo usando HashSet<t> como la aplicación concreta de ISet<T>:

public class Broker : ActiveDefaultEntity 
{ 
    public virtual string Name { get; set; } 
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; } 

    public Broker() { 
     BrokerInstruments = new HashSet<BrokerInstrument>(); 
    } 
} 

public class Instrument : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual string Symbol {get; set;} 
    public virtual ISet<BrokerInstrument> BrokerInstruments { get; set; } 
    public virtual bool IsActive { get; set; } 

    public Instrument() { 
     BrokerInstruments = new HashSet<BrokerInstrument>(); 
    }  
} 

A continuación, debe agregar el objeto brokerInstrument tanto a los conjuntos-BrokerInstruments de Instrument y Broker:

var instrument = new Instrument { 
    Name = "Test Instrument", 
    Symbol = "Test", 
    IsActive = true 
}; 
var broker = new Broker { 
    Name = "My Test Broker", 
    IsActive = true, 
    IsDefault = false 
}; 
var brokerInstrument = new BrokerInstrument { 
    Broker = broker, 
    Instrument = instrument, 
    MinIncrement = 0.01M 
}; 
instrument.BrokerInstruments.Add(brokerInstrument); 
broker.BrokerInstruments.Add(brokerInstrument); 
+0

Gracias, tuve que hacerlo así debido a conflictos de espacios de nombres y errores de conversión: 'BrokerInstruments = (ISet ) new System.Collections.Generic.HashSet ();' –

+0

¡Genial! Por favor acepte la respuesta si fue útil. –

0

You instrument.BrokerInstruments no inicializado. Es necesario : instrument.BrokerInstruments = new ...; supongo nueva HashSet o una nueva SortedSet

Cuestiones relacionadas