C# NHibernate集合获取、复制数据
我有一个复杂的情况,我需要用NHibernate映射三个不同的类。Class1(Branch.cs)有一个Class2(Employee.cs)对象的集合。同时,Class2还有一个Class3(Contacts.cs)对象的集合C# NHibernate集合获取、复制数据,c#,.net,nhibernate,C#,.net,Nhibernate,我有一个复杂的情况,我需要用NHibernate映射三个不同的类。Class1(Branch.cs)有一个Class2(Employee.cs)对象的集合。同时,Class2还有一个Class3(Contacts.cs)对象的集合 由于数据非常庞大,我使用fetch关键字在单个查询中检索数据。 我将查询用作 查询1—“来自分支机构b内部联接获取b.员工e内部联接获取e.联系人”-单个查询,但结果重复。 查询2-“从分支机构b内部联接获取b.Employee”-多个查询,必需的结果。 我在映
由于数据非常庞大,我使用fetch关键字在单个查询中检索数据。
我将查询用作
查询1—“来自分支机构b内部联接获取b.员工e内部联接获取e.联系人”-单个查询,但结果重复。
查询2-“从分支机构b内部联接获取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>
<?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>
<?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>
Employee.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; }
}
}
}
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()
{ }
}
}
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() { }
}
}
使用系统;
使用System.Collections.Generic;
使用系统文本;
名称空间NHibernateSample
{
公营雇员
{
字符串employeeId;
字符串名;
字符串lastName;
字符串分支代码;
列表联系人=新列表();
公共虚拟列表联系人
{
获取{返回联系人;}
设置{contact=value;}
}
公共虚拟字符串EmployeeId
{
获取{return employeeId;}
设置{employeeId=value;}
}
公共虚拟字符串名
{
获取{return firstName;}
设置{firstName=value;}
}
公共虚拟字符串LastName
{
获取{return lastName;}
设置{lastName=value;}
}
公共虚拟字符串分支代码
{
获取{return branchCode;}
设置{branchCode=value;}
}
公职人员()
{ }
}
}
Branch.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; }
}
}
}
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()
{ }
}
}
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() { }
}
}
使用System.Collections.Generic;
使用系统文本;
使用制度;
名称空间NHibernateSample
{
[可序列化]
公营部门
{
私有字符串分支代码;
私有字符串分支名称;
私有IList employeeList=新列表();
公共虚拟IList员工列表
{
获取{return employeeList;}
设置{employeeList=value;}
}
公共虚拟字符串分支代码
{
获取{return branchCode;}
设置{branchCode=value;}
}
公共虚拟字符串BranchName
{
获取{return branchName;}
设置{branchName=value;}
}
公共分支(){}
}
}
这是NHibernate的一个问题,他们不会解决
通过应用distincentitytransformer,您可以在第一级获得正确的结果,这是NHibernate中的内置转换器,您应该使用
QueryOver.TranformUsing(Tranformers.DistinctEntityTransformer).
在诸如您的问题之类的多层次问题上,您需要编写自己的转换器,并使用它而不是独特的实体转换器。您可以使用与NHibernate提供的distinct entity transformer类似的逻辑来修复细节处的复制
编辑:以下是此的一个实现:
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);
}
}
}
}
public class多级distinctentytransformer:IResultTransformer
{
私有只读字典_fetchedCollectionProperties;//用于知道获取了哪些属性,因此不会获取比所需更多的详细信息
公共多级distinctentytransformer(字典获取的集合属性)
{
_fetchedCollectionProperties=fetchedCollectionProperties;
}
公共对象转换元组(对象[]元组,字符串[]别名)
{
返回tuple.Last();
}
公共IList列表(IList列表)
{
如果(list.Count==0)
退货清单;
var result=(IList)Activator.CreateInstance(list.GetType());
var distinctSet=new HashSet();
foreach(列表中的对象项)
{
var entity=item as entity;//entity是我的nhibernate类的基类
if(实体==null)
继续;
if(distinctSet.Add(实体))
{
结果.添加(项目);
HandleItemDetails(项目);
}
}
返回结果;
}
私有无效HandleItemDetails(对象项)
{
IEnumerable collectionProperties=
item.GetType().GetProperties().Where(
道具=>
prop.IsCollectionProperty()/*扩展方法,用于检查对象是否继承自ICollection*/&&
_fetchedCollectionProperties.ContainsKey(item.GetType())&&&//仅获取获取的详细信息
_fetchedCollectionProperties[item.GetType()]包含(prop.Name));
foreach(collectionProperties中的PropertyInfo collectionProperty)
{
dynamic detailList=collectionProperty.GetValue(项,空);
if(detailList!=null)
{
动态唯一值=
Activator.CreateInstance(
typeof(List).MakeGenericType(collectionProperty.PropertyType.GetGenericArguments()[0]);
var distinct=newhashset();
foreach(明细表中的var子项)
{
var实体=作为实体的子项;
if(独立添加(实体))
{
唯一值。添加(子项);
详细资料(分项);
}
}
SetValue(项,唯一值,空);
}
}
}
}
我将在我的应用程序中实现它。目前,我正在寻找一些其他的选择,如批量大小的内部收集。如果将lazy=false和批处理大小设置为数千个,它会起作用吗