Unable to cast 'NHibernate.Collection.Generic.PersistentGenericSet`1 to System.Collections.Generic.IList`1

2,829 views
Skip to first unread message

Riderman Sousa

unread,
May 24, 2013, 4:12:55 PM5/24/13
to Fluent NHibernate Group

I have a domain class:


public class Agencia : IEntity
{
    public virtual int Id { get; set; }

    public virtual string Nome { get; set; }

    public virtual string Identificacao { get; set; }

    public virtual IList<Pessoa> Gerentes { get; protected set; }

    public Agencia()
    {
        Gerentes = new List<Pessoa>();
    }

    public virtual void AddGerente(Pessoa gerente)
    {
        Gerentes.Add(gerente);
    }
    public virtual void AddGerentes(params Pessoa[] gerentes)
    {
        Parallel.ForEach(gerentes, (pessoa) => Gerentes.Add(pessoa));
    }
}

public class Pessoa: IEntity
{
    public virtual int Id { get; set; }

    public virtual string Nome { get; set; }

}

With this convention (defined as set AsSet)

public class AgenciaConvention : IAutoMappingOverride<Agencia>
{
    public void Override(AutoMapping<Agencia> mapping)
    {
        mapping.HasManyToMany(a => a.Gerentes).Cascade.AllDeleteOrphan().AsSet().Not.Inverse();
    }
}

When I run this test:


[TestMethod]
[Description("Uma agência tem vários gerêntes")]
public void AgenciaTemVariosGerentes()
{
    // Arrange
    var fix = new Fixture();
    var currentUser = GetLoggedUser();

    // Create a List<Pessoa>

    var gerentes = fix.Build<Pessoa>()
                        .With(p => p.Nome)
                        .With(p => p.CPF)
                        .With(p => p.CreateBy, currentUser)
                        .OmitAutoProperties()
                        .CreateMany<Pessoa>(10).ToList();

    // Action

    new PersistenceSpecification<Agencia>(Session)
            .CheckProperty(p => p.Nome, fix.Create<string>().Truncate(80))
            .CheckProperty(p => p.Identificacao, fix.Create<string>().Truncate(10))
            .CheckReference(p => p.Regional,
                fix.Build<Regional>()
                    .With(p => p.Nome)
                    .OmitAutoProperties()
                    .Create()
            , new IDEqualityComparer())
            .CheckList(p => p.Gerentes, gerentes, new IDEqualityComparer())
            .CheckReference(p => p.CreateBy, currentUser, new IDEqualityComparer())
            .VerifyTheMappings(); // Assert
}

How can I test this list?

The collection should be AsSet, it necessary that the Parent and Children fields are PK, FK

Error:


Test Name: AgenciaTemVariosGerentes
Test FullName: {OMMITED}.Integration.Test.AgenciaTest.AgenciaTemVariosGerentes
Test Source: {OMMITED}.Integration.Test\AgenciaTest.cs : line 22
Test Outcome: Failed
Test Duration: 0:00:02,4093555

Result Message:
Test method {OMMITED}.Integration.Test.AgenciaTest.AgenciaTemVariosGerentes threw exception: 
NHibernate.PropertyAccessException: Invalid Cast (check your mapping for property type mismatches); setter of CreditoImobiliarioBB.Model.Regional ---> System.InvalidCastException: Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericSet`1[CreditoImobiliarioBB.Model.Pessoa]' to type 'System.Collections.Generic.IList`1[CreditoImobiliarioBB.Model.Pessoa]'.
Result StackTrace:
at (Object , Object[] , SetterCallback )
   at NHibernate.Bytecode.Lightweight.AccessOptimizer.SetPropertyValues(Object target, Object[] values)
   at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)
 --- End of inner exception stack trace ---
    at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)
   at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValues(Object entity, Object[] values)
   at NHibernate.Persister.Entity.AbstractEntityPersister.SetPropertyValues(Object obj, Object[] values, EntityMode entityMode)
   at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
   at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
   at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
   at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
   at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
   at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
   at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
   at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
   at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
   at NHibernate.Impl.SessionImpl.Save(Object obj)
   at FluentNHibernate.Testing.PersistenceSpecification`1.TransactionalSave(Object propertyValue)
   at FluentNHibernate.Testing.Values.ReferenceProperty`2.HasRegistered(PersistenceSpecification`1 specification)
   at FluentNHibernate.Testing.PersistenceSpecification`1.RegisterCheckedProperty(Property`1 property, IEqualityComparer equalityComparer)
   at FluentNHibernate.Testing.PersistenceSpecificationExtensions.CheckReference[T](PersistenceSpecification`1 spec, Expression`1 expression, Object propertyValue, IEqualityComparer propertyComparer)
   at CreditoImobiliarioBB.Repository.Integration.Test.AgenciaTest.AgenciaTemVariosGerentes() in {OMMITED}.Integration.Test\AgenciaTest.cs:line 27

Thanks.

Riderman de Sousa Barbosa

Web Developer | MCPD Certify

Skype.: 4042-6002 | Cel.: (31) 8681-1986

bindsolution.com

Microsoft Parner Network

Carl Bussema

unread,
May 24, 2013, 4:24:33 PM5/24/13
to fluent-n...@googlegroups.com
If you're mapping as a set, you need to use Iesi.Collections.Generic.ISet<T> as the object type in your domain (implemented by HashedSet<T> normally).



--
You received this message because you are subscribed to the Google Groups "Fluent NHibernate" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fluent-nhibern...@googlegroups.com.
To post to this group, send email to fluent-n...@googlegroups.com.
Visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Riderman Sousa

unread,
May 24, 2013, 5:07:06 PM5/24/13
to Fluent NHibernate Group
I do not want to create a new dependency in my domain. Because if I have to migrate ORM this can be a problem.

Is there any way to accomplish this without creating a dependency?

Riderman Sousa

unread,
May 24, 2013, 7:14:36 PM5/24/13
to Fluent NHibernate Group

Even after installing the package via nuget Iesi.Collections I can not set my collection as ISet <>;


Inline image 1

Inline image 2
image.png
image.png

Oskar Berggren

unread,
May 25, 2013, 5:25:55 AM5/25/13
to fluent-n...@googlegroups.com
You have download iesi.collections 4.0 which is for use with .Net 4 (where ISet is builtin) and the future NHibernate 4.0.

You should use the iesi.collections included with your copy of NHibernate.

/Oskar


2013/5/25 Riderman Sousa <rider...@bindsolution.com>
image.png
image.png

Oskar Berggren

unread,
May 25, 2013, 5:27:02 AM5/25/13
to fluent-n...@googlegroups.com
If you get (a recent) NHibernate via Nuget it should resolve to the correct Iesi dependency automatically.

/Oskar



2013/5/25 Oskar Berggren <oskar.b...@gmail.com>
image.png
image.png

Riderman Sousa

unread,
May 27, 2013, 8:29:21 AM5/27/13
to Fluent NHibernate Group

ISet not in Iesi.Collections.dll, or has some dependency with NHibernate.
I can not install NHibernate on my domain layer!

Anyway, I found the solution).

Thanks.


Riderman de Sousa Barbosa

Web Developer | MCPD Certify

Skype.: 4042-6002 | Cel.: (31) 8681-1986

bindsolution.com

Microsoft Parner Network

image.png
image.png

Oskar Berggren

unread,
May 27, 2013, 8:41:53 AM5/27/13
to fluent-n...@googlegroups.com
Not sure what you mean, bug nuget NHibernate 3.3.3 (http://nuget.org/packages/NHibernate/3.3.3.4000) definitely depends on Iesi.Collections 3.x (which include ISet).  If you have a nuget NHibernate package older than 3.3.2 it might install the wrong Iesi.Collections version (but then NHibernate won't run at all).

If you downloaded NHibernate binaries from sourceforge, the package includes the Iesi.Collections library.

In either case, if you had a version of NHibernate running, the Iesi.Collections library should have already been there, since NHibernate won't run without it.

/Oskar



2013/5/27 Riderman Sousa <rider...@bindsolution.com>
image.png
image.png

Riderman Sousa

unread,
May 27, 2013, 12:26:25 PM5/27/13
to Fluent NHibernate Group

Yes, I tried installing just the Iesi.Collections) in my domain layer (without installing NHibernate).

I did not want to have the ORM as dependency in my domain layer;

I do not know why, but when I installed Iesi.Collection could not use ISet.
Anyway, I do not have but need since ICollection can be used in its place!

image.png
image.png

Carl Bussema

unread,
May 27, 2013, 12:45:29 PM5/27/13
to fluent-n...@googlegroups.com

Icollection will not enforce uniqueness. You will need to have your domain do that or risk exceptions.

image.png
image.png

Riderman Sousa

unread,
May 27, 2013, 1:38:34 PM5/27/13
to Fluent NHibernate Group
Carl, I do not see much problems with that.

What guarantees the uniqueness is the `Id` of an entity.
Once access to the Id property is protected, and the database has one constraint (unique/pk) I do not see how it could generate exceptions;

How do you usually work?
In my case, Id is generated by database and the Id property is as protected.



image.png
image.png

Carl Bussema

unread,
May 27, 2013, 2:11:13 PM5/27/13
to fluent-n...@googlegroups.com

If you add the same item to the collection multiple times, nh will try to add the relationship twice. This may violate pk or unique key constraints. Look at the documentation for set vs bag vs list.

image.png
image.png

Riderman Sousa

unread,
May 27, 2013, 6:07:36 PM5/27/13
to Fluent NHibernate Group

I see, interesting.

But I really do not see many benefits in using Iese.Collections, because even if you try to add the same item multiple times in a collection or will generate an exception Database or CLR.
Anyway add the same item twice should and will generate an exception.

But I agree with you that as soon thrown as the exception is better. In this case, it would be better to throw exception on server level first.

Anyway, the collections on my app are of type) ICollection<> and by convention AsSet Are initialized with HashSet<>

NHibernate as a dependency in my domain layer is a break designer in my app, I do not see many options.



image.png
image.png

Alexander I. Zaytsev

unread,
May 27, 2013, 6:18:16 PM5/27/13
to fluent-n...@googlegroups.com
Hi there,

The problem there that NHibernate was here a long time before Microsoft introduced ISet<>/HashSet to BCL. So Iesi.Collection has been written to cover lack of sets.

If you do want to use System.Collections.Generic.ISet<> and System.Collections.Generic.HashSet<> instead of Iesi you need to take a look over http://nuget.org/packages/NHibernate.SetForNet4/ package.

But anyway Iesi.Collections should be installed because NHibenate has dependencies on it.

Regards,
Alex
image.png
image.png
Reply all
Reply to author
Forward
0 new messages