gpt4 book ai didi

c# - NHibernate Collection of collections fetching, 重复数据

转载 作者:行者123 更新时间:2023-12-02 05:33:59 29 4
gpt4 key购买 nike

我的情况很复杂,我需要用 NHibernate 映射三个不同的类。 Class1(Branch.cs) 具有 Class2(Employee.cs) 对象的集合。同时Class2还有一个Class3(Contacts.cs)对象的集合。
由于数据非常庞大,我使用 fetch 关键字在单个查询中检索数据。
我将查询用作

Query1 - “from Branch b inner join fetch b.Employee e inner join fetch e.Contacts” - 单个查询但结果重复。
Query2 - “from Branch b inner join fetch b.Employee” - 多个查询,需要结果。

我在映射文件中使用了包。查询结果似乎有重复的结果。如何删除重复结果以及在单个查询中检索数据。我包括映射文件和类。

Contacts.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateSample" namespace="NHibernateSample">
<class name="Contacts" table="Contacts">
<id name="EmployeeID"/>
<property name="EmployeeID"/>
<property name="Mobile"/>
<property name="Alternate"/>
</class>
</hibernate-mapping>

Branch.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateSample" namespace="NHibernateSample">
<class name="Branch" table="Branch">
<id name="BranchCode"/>
<property name="BranchCode"/>
<property name="BranchName"/>
<bag name="EmployeeList" cascade="all-delete-orphan" inverse="false" batch-size="10000">
<key column="BranchCode"/>
<one-to-many class="Employee" />
</bag>
</class>

</hibernate-mapping>

员工.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateSample" namespace="NHibernateSample">
<class name="Employee" table="Employee">
<id name="EmployeeId"/>
<property name="EmployeeId"/>
<property name="FirstName"/>
<property name="LastName"/>
<property name="BranchCode"/>
<bag name="Contact" cascade="all-delete-orphan" inverse="false" batch-size="10000">
<key column="EmployeeID"/>
<one-to-many class="Contacts" />
</bag>
</class>
</hibernate-mapping>

Contacts.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace NHibernateSample
{
public class Contacts
{
String employeeID;
String mobile;
String alternate;

public Contacts()
{ }


public virtual String EmployeeID
{
get { return employeeID; }
set { employeeID = value; }
}

public virtual String Mobile
{
get { return mobile; }
set { mobile = value; }
}
public virtual String Alternate
{
get { return alternate; }
set { alternate = value; }
}
}
}

Employee.cs

    using System;
using System.Collections.Generic;
using System.Text;

namespace NHibernateSample
{
public class Employee
{
String employeeId;
String firstName;
String lastName;
String branchCode;
List<Contacts> contact = new List<Contacts>();

public virtual List<Contacts> Contact
{
get { return contact; }
set { contact = value; }
}
public virtual String EmployeeId
{
get { return employeeId; }
set { employeeId = value; }
}

public virtual String FirstName
{
get { return firstName; }
set { firstName = value; }
}

public virtual String LastName
{
get { return lastName; }
set { lastName = value; }
}

public virtual String BranchCode
{
get { return branchCode; }
set { branchCode = value; }
}

public Employee()
{ }
}
}

Branch.cs

    using System.Collections.Generic; 
using System.Text;
using System;


namespace NHibernateSample
{
[Serializable]
public class Branch
{
private String branchCode;
private String branchName;
private IList<Employee> employeeList = new List<Employee>();

public virtual IList<Employee> EmployeeList
{
get { return employeeList; }
set { employeeList = value; }
}
public virtual String BranchCode
{
get { return branchCode; }
set { branchCode = value; }
}

public virtual String BranchName
{
get { return branchName; }
set { branchName = value; }
}

public Branch() { }
}
}

最佳答案

这是 NHibernate 的一个问题,他们不会修复。

您可以通过应用 DistinctEntityTransformer 在第一级获得正确的结果,这是 NHibernate 中的内置转换器,您应该使用

将其应用于查询对象
QueryOver.TranformUsing(Tranformers.DistinctEntityTransformer).

在多层次上,例如您的问题,您需要编写自己的转换器并使用它来代替不同的实体转换器。您可以使用与 NHibernate 提供的不同实体转换器类似的逻辑来修复细节上的复制。

编辑:这是一个实现:

public class MultiLevelDistinctEntityTransformer : IResultTransformer
{
private readonly Dictionary<Type, List<String>> _fetchedCollectionProperties; // used to know which properties are fetched so you don't fetch more details than required

public MultiLevelDistinctEntityTransformer(Dictionary<Type, List<String>> fetchedCollectionProperties)
{
_fetchedCollectionProperties = fetchedCollectionProperties;
}

public object TransformTuple(object[] tuple, string[] aliases)
{
return tuple.Last();
}

public IList TransformList(IList list)
{
if (list.Count == 0)
return list;
var result = (IList) Activator.CreateInstance(list.GetType());
var distinctSet = new HashSet<Entity>();
foreach (object item in list)
{
var entity = item as Entity; // Entity is the base class of my nhibernate classes
if (entity == null)
continue;
if (distinctSet.Add(entity))
{
result.Add(item);
HandleItemDetails(item);
}
}
return result;
}

private void HandleItemDetails(object item)
{
IEnumerable<PropertyInfo> collectionProperties =
item.GetType().GetProperties().Where(
prop =>
prop.IsCollectionProperty()/*extension method which checks if the object inherits from ICollection*/ &&
_fetchedCollectionProperties.ContainsKey(item.GetType()) &&// get only the fetched details

_fetchedCollectionProperties[item.GetType()].Contains(prop.Name));
foreach (PropertyInfo collectionProperty in collectionProperties)
{
dynamic detailList = collectionProperty.GetValue(item, null);
if (detailList != null)
{
dynamic uniqueValues =
Activator.CreateInstance(
typeof (List<>).MakeGenericType(collectionProperty.PropertyType.GetGenericArguments()[0]));
var distinct = new HashSet<Entity>();
foreach (var subItem in detailList)
{
var entity = subItem as Entity;
if (distinct.Add(entity))
{
uniqueValues.Add(subItem);
HandleItemDetails(subItem);
}
}
collectionProperty.SetValue(item, uniqueValues, null);
}
}
}
}

关于c# - NHibernate Collection of collections fetching, 重复数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11950502/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com