简体   繁体   中英

NHibernate fetchmany duplicated values repository pattern

I have a problem with duplicated results in list for my query.

What I have is two FetchMany on a method for my repository:

    public IQueryable<MyEntity> Query()
    {
        return Session.Query<MyEntity>()
            .FetchMany(x => x.ListA)
            .FetchMany(x => x.ListB);
    }

Query:

var result = _myEntityRepository
    .Query()
    .Where(x => names.Contains(x.Name))
    .Where(x => x.ListA.Any(m => listAIds.Contains(m.Id)))
    .Where(x => x.ListB.Any(m => listBIds.Contains(m.Id)))
    .OrderBy(x => x.CreationDate)
    .ToList();

Mapping:

        HasManyToMany(x => x.ListA)
            .Table("MY_ENTITY_TYPE_A")
            .ParentKeyColumn("MYENTITY_ID")
            .ChildKeyColumn("MYENTITYA_ID")
            .Fetch.Join();

ListA is class MyEntityA with several properties.

ListB is class MyEntityB with several properties.

The SQL produced is good and gets the values I need, how ever the values added to ListA and ListB gets duplicated several times. ListA and ListB are seperate tables (many to many).

I use fluent-nhibernate .

I looked up using ToFuture but that only gave me Method Not Implemented Exception and I don't want to use NHibernate outside my repository.

Here is what I tried:

    public IQueryable<MyEntity> Query()
    {
        var query = Session.Query<MyEntity>();

        Session.Query<MyEntity>().FetchMany(x => x.ListA).ToFuture();
        Session.Query<MyEntity>().FetchMany(x => x.ListB).ToFuture();

        return query;
    }

Exception is thrown at:

        Session.Query<MyEntity>().FetchMany(x => x.ListA).ToFuture();

TargetInvocationException is thrown with inner exception "The method or operation is not implemented."

Stack trace:

   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at NHibernate.Linq.DefaultQueryProvider.ExecuteFutureQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery)
   at NHibernate.Linq.DefaultQueryProvider.ExecuteFuture(Expression expression)
   at NHibernate.Linq.LinqExtensionMethods.ToFuture[T](IQueryable`1 query)

How can accomplish this? At the moment I do Disctint on ListA and ListB, but it seems to be slower and not so nice with all the duplicated values in the entities created.

MyEntity has many items of EntityA in ListA and many items of EntityB in ListB, but there are no duplicates in the database.

Note: I have to use FetchMany for both, else there will be too many select queries!

Getting ToFuture to work will be important. x.ListA X x.ListB is a Cartesian product. ToFuture should work. Can you provide more details on your attempt at using it?

Ignoring the Cartesian product, you can get your current approach to work by using <set/> instead of <bag/> when mapping ListA and ListB . This tells NHibernate that the collections should not contain duplicates. Normally this wouldn't be necessary, but including both ListA and ListB in the same query is creating the duplicate results. <set/> should fix this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM