1

I try to query data using FluentNhibernate and I get this error: "Sequence contains more than one matching element"

Here are my classes and mappings:

public class Course
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual IList<Instructor> Instructors { get; set; }
}

public class Instructor
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual ImageData Portrait { get; set; }
    public virtual ImageData PortraitThumb { get; set; }
    public virtual IList<Course> TeachingCourses { get; private set; }
}

public class ImageData : Entity
{
    public virtual int Id { get; private set; }
    public virtual byte[] Data { get; set; }
}

public class CourseMap : ClassMap<Course>
{
    public CourseMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        HasManyToMany(x => x.Instructors)
            .Cascade.All()
            .Table("CourseInstructor");
    }
}

public class InstructorMap : ClassMap<Instructor>
{
    public InstructorMap()
    {
        Id(x => x.Id);
        Map(x=> x.Name);
        References(x => x.Portrait)
            .Nullable()
            .Cascade.All();
        References(x => x.PortraitThumb)
            .Nullable()
            .Cascade.All();
        HasManyToMany(x => x.TeachingCourses)
            .Cascade.All()
            .Inverse()
            .Table("CourseInstructor");
    }
}

public class ImageDataMap : ClassMap<ImageData>
{
    public ImageDataMap()
    {
        Id(x => x.Id);
        Map(x => x.Data);
    }
}

Then I try to get data using below code:

var course = session.CreateCriteria(typeof(Course))
               .SetFetchMode("Instructors", FetchMode.Eager)
               .SetFetchMode("Instructors.Portrait", FetchMode.Eager)
               .SetFetchMode("Instructors.PortraitThumb", FetchMode.Eager)
               .List<Course>();

But I get the following error: "Sequence contains more than one matching element" Also, when I try this

var course = session.CreateCriteria(typeof(Course))
               .SetFetchMode("Instructors", FetchMode.Eager)
               .SetFetchMode("Instructors.Portrait", FetchMode.Eager)
               .SetFetchMode("Instructors.PortraitThumb", FetchMode.Eager)                   
               .SetResultTransformer(new DistinctRootEntityResultTransformer())
               .List<Course>();

No error occurs but I get duplicate Instructor objects.

I did try below posts and some others as well. But it doesn't help.

Community
  • 1
  • 1
Siripongz
  • 89
  • 2
  • 7
  • Can you post what you expect to retrieve and what you actually retrieve? I suppose the issue is caused by the usage of `IList` instead of `ISet`. – Andreas May 06 '12 at 13:34

1 Answers1

0

FluentNhibernate uses a bag-mapping for many-to-many relations, if the mapped property is of type IList.

A bag mapping has a few major drawbacks Performance of Collections / hibernate. The one that currently bites you is that NH does not permit duplicate element values and, as they have no index column, no primary key can be defined.

Simply said NH does not know to which bag do they belong to when you join them all together.

Instead of a bag I would use a indexed variant a set, assuming that an Instructor does not has the same persistent Course assigned twice.

You can fix your query results by amending your domain classes, this tells FluentNhibernate to use a set instead of a bag by convention:

public class Course
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual Iesi.Collections.Generic.ISet<Instructor> Instructors { get; set; }
}

public class Instructor
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual ImageData Portrait { get; set; }
    public virtual ImageData PortraitThumb { get; set; }
    public virtual Iesi.Collections.Generic.ISet<Course> TeachingCourses { get; private set; }
}

In addition you can amend your mapping by using .AsSet(). FluentNHibernate: What is the effect of AsSet()?

Community
  • 1
  • 1
Andreas
  • 5,251
  • 30
  • 43
  • Thank you very much. It's work now. but when I use `Iesi.Collections.ISet`, I got this error => "The non-generic type 'Iesi.Collections.ISet' cannot be used with type arguments" Then, I use ICollection instead. – Siripongz May 06 '12 at 16:09
  • @Siripongz: I did not test the code and googled for the wrong namespace `Iesi.Collections.ISet` instead of `Iesi.Collections.Generic.ISet`. I updated the answer. Thank you for finding the error. – Andreas May 06 '12 at 17:03