如何避免NHibernate N+;1具有复合键
编辑我为这个问题重新制作了整个项目。因此,我重新提出了这个问题 我希望能够有效地避免N+1和笛卡尔连接,将4层深度的实体与第三层上的复合关键点连接在一起 我希望这只在几个查询中完成,而不是延迟加载,也不是将所有表连接在一起 A-(多)->B-(多)->C-(复合,单)->D 比如:如何避免NHibernate N+;1具有复合键,nhibernate,queryover,select-n-plus-1,Nhibernate,Queryover,Select N Plus 1,编辑我为这个问题重新制作了整个项目。因此,我重新提出了这个问题 我希望能够有效地避免N+1和笛卡尔连接,将4层深度的实体与第三层上的复合关键点连接在一起 我希望这只在几个查询中完成,而不是延迟加载,也不是将所有表连接在一起 A-(多)->B-(多)->C-(复合,单)->D 比如: Select * From A Left Join B On A.Id = B.AId Select * From B Left Join C On B.Id = C.BId Inner Join D On C.DI
Select * From A Left Join B On A.Id = B.AId
Select * From B Left Join C On B.Id = C.BId Inner Join D On C.DId = D.Id
下面是使用的代码
这是一个功能齐全的应用程序。
我使用NuGet安装Sqlite x86、StructureMap、NHProf和Fluent NH
StructureMapServiceLocator:
namespace MyTest.NHibernateTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using StructureMap;
public class StructureMapServiceLocator : ServiceLocatorImplBase
{
private readonly IContainer _container;
public StructureMapServiceLocator(IContainer container)
{
_container = container;
}
public IContainer Container { get { return _container; } }
protected override object DoGetInstance(Type serviceType, string key)
{
return string.IsNullOrEmpty(key)
? _container.GetInstance(serviceType)
: _container.GetInstance(serviceType, key);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
return _container.GetAllInstances(serviceType).Cast<object>().AsEnumerable();
}
public override TService GetInstance<TService>()
{
return _container.GetInstance<TService>();
}
public override TService GetInstance<TService>(string key)
{
return _container.GetInstance<TService>(key);
}
public override IEnumerable<TService> GetAllInstances<TService>()
{
return _container.GetAllInstances<TService>();
}
}
}
名称空间MyTest.NHibernateTest
{
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用Microsoft.Practices.ServiceLocation;
使用结构图;
公共类StructureMapServiceLocator:ServiceLocatorImplBase
{
专用只读IContainer\u容器;
公共结构MapServiceLocator(IContainer容器)
{
_容器=容器;
}
公共IContainer容器{get{return\u Container;}}
受保护的重写对象DoGetInstance(类型serviceType,字符串键)
{
返回字符串.IsNullOrEmpty(键)
?_container.GetInstance(serviceType)
:_container.GetInstance(serviceType,key);
}
受保护的重写IEnumerable DoGetAlliances(类型serviceType)
{
return _container.GetAllInstances(serviceType.Cast().AsEnumerable();
}
公共覆盖TService GetInstance()
{
返回_container.GetInstance();
}
公共覆盖TService GetInstance(字符串键)
{
return\u container.GetInstance(key);
}
公共重写IEnumerable GetAllInstances()
{
return_container.GetAllInstances();
}
}
}
评价学
namespace MyTest.NHibernateTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using StructureMap.Configuration.DSL;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Cfg;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using FluentNHibernate.Automapping;
using FluentNHibernate.Data;
public class AppRegistry : Registry
{
public AppRegistry()
{
var dbConfiguration = SQLiteConfiguration.Standard
.ConnectionString("Data Source=sqlite.db;Version=3;New=True;");
dbConfiguration.ShowSql();
var cfg = Fluently.Configure()
.Database(dbConfiguration)
.Mappings(m =>
{
m.AutoMappings.Add(AutoMap.AssemblyOf<Program>().Where(t =>
{
return typeof(Entity).IsAssignableFrom(t);
}));
})
.ExposeConfiguration(c =>
{
if (RebuildSchema.Value)
new SchemaExport(c).Create(false, true);
});
var sessionFactory = cfg.BuildSessionFactory();
For<ISessionFactory>().Singleton().Use(sessionFactory);
For<ISession>().HybridHttpOrThreadLocalScoped().Use(cx =>
{
var session = cx.GetInstance<ISessionFactory>().OpenSession();
session.FlushMode = FlushMode.Commit;
return session;
});
}
}
}
名称空间MyTest.NHibernateTest
{
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用StructureMap.Configuration.DSL;
使用FluentNHibernate.Cfg.Db;
使用FluentNHibernate.Cfg;
使用NHibernate;
使用NHibernate.Tool.hbm2ddl;
使用FluentNHibernate.自动映射;
使用FluentNHibernate.Data;
公共类权限:注册表
{
公共评估学()
{
var dbConfiguration=SQLiteConfiguration.Standard
.ConnectionString(“数据源=sqlite.db;版本=3;新建=True;”;
dbConfiguration.ShowSql();
var cfg=fluntly.Configure()
.数据库(数据库配置)
.Mappings(m=>
{
m、 添加(AutoMap.AssemblyOf()。其中(t=>
{
返回类型(实体)。IsAssignableFrom(t);
}));
})
.ExposeConfiguration(c=>
{
if(重建模式值)
新建SchemaExport(c).Create(false,true);
});
var sessionFactory=cfg.BuildSessionFactory();
For().Singleton().Use(sessionFactory);
For().HybridHttpOrthReadLocalScope().Use(cx=>
{
var session=cx.GetInstance().OpenSession();
session.FlushMode=FlushMode.Commit;
返回会议;
});
}
}
}
上市实体:
namespace MyTest.NHibernateTest.Entities
{
using System;
using System.Collections.Generic;
using System.Linq;
using FluentNHibernate.Data;
public class Listing : Entity
{
public Listing()
{
Items = new List<ListingItem>();
}
public virtual IList<ListingItem> Items { get; set; }
}
public class ListingItem : Entity
{
public ListingItem()
{
Values = new List<ListingItemValue>();
}
public virtual IList<ListingItemValue> Values { get; set; }
}
public class ListingItemValue : Entity
{
public virtual ListingItem ListingItem { get; set; }
public virtual ListingItemField ListingItemField { get; set; }
}
public class ListingItemField : Entity
{
public virtual string Value { get; set; }
}
}
名称空间MyTest.NHibernateTest.Entities
{
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用FluentNHibernate.Data;
公共类列表:实体
{
公开上市()
{
项目=新列表();
}
公共虚拟IList项{get;set;}
}
公共类ListingItem:实体
{
公共列表项()
{
值=新列表();
}
公共虚拟IList值{get;set;}
}
公共类ListingItemValue:实体
{
公共虚拟ListingItem ListingItem{get;set;}
公共虚拟ListingItemField ListingItemField{get;set;}
}
公共类ListingItemField:实体
{
公共虚拟字符串值{get;set;}
}
}
程序(控制台):
名称空间MyTest.NHibernateTest
{
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用结构图;
使用hibertingrhinos.Profiler.Appender.NHibernate;
使用Microsoft.Practices.ServiceLocation;
使用NHibernate;
使用系统线程;
使用NHibernate.Transform;
使用MyTest.NHibernateTest.Entities;
公共静态类重建模式
{
公共静态布尔值{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
RebuildSchema.Value=true;
设置();
BuildData();
工作();
Console.ReadLine();
}
静态无效设置()
{
NHibernateProfiler.Initialize();
ObjectFactory.Initialize(x=>
{
x、 扫描(s=>
{
s、 装配件();
s、 查找注册表();
});
});
ServiceLocator.SetLocatorProvider(()=>new StructureMapServiceLocator(ObjectFactory.Container));
}
静态void BuildData()
{
var s=ObjectFactory.GetInstance();
使用(var t=s.BeginTransaction())
{
var listing=新列表();
s、 保存(列表);
var item=new ListingItem();
listing.Items.Add(item);
s、 保存(项目);
var item2=新列表项();
listing.Items.Add(item2);
s、 保存(项目2);
var field=new ListingItemField();
field.Value=“A”;
s、 保存(字段);
var field2=新的ListingItemField();
field2.Value=“B”;
s、 保存(字段2);
var值=新的ListingItemValue();
value.ListingItem=项目;
value.ListingItemField=字段;
项目.价值.增加(价值);
s、 保存(价值);
var value2=新的ListingItemValue();
value2.ListingItem=项目;
value2.ListingItemField=field2;
项目.价值.增加(价值2);
s、 保存(价值2);
namespace MyTest.NHibernateTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using StructureMap;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using Microsoft.Practices.ServiceLocation;
using NHibernate;
using System.Threading;
using NHibernate.Transform;
using MyTest.NHibernateTest.Entities;
public static class RebuildSchema
{
public static bool Value { get; set; }
}
class Program
{
static void Main(string[] args)
{
RebuildSchema.Value = true;
Setup();
BuildData();
Work();
Console.ReadLine();
}
static void Setup()
{
NHibernateProfiler.Initialize();
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.TheCallingAssembly();
s.LookForRegistries();
});
});
ServiceLocator.SetLocatorProvider(() => new StructureMapServiceLocator(ObjectFactory.Container));
}
static void BuildData()
{
var s = ObjectFactory.GetInstance<NHibernate.ISession>();
using (var t = s.BeginTransaction())
{
var listing = new Listing();
s.Save(listing);
var item = new ListingItem();
listing.Items.Add(item);
s.Save(item);
var item2 = new ListingItem();
listing.Items.Add(item2);
s.Save(item2);
var field = new ListingItemField();
field.Value = "A";
s.Save(field);
var field2 = new ListingItemField();
field2.Value = "B";
s.Save(field2);
var value = new ListingItemValue();
value.ListingItem = item;
value.ListingItemField = field;
item.Values.Add(value);
s.Save(value);
var value2 = new ListingItemValue();
value2.ListingItem = item;
value2.ListingItemField = field2;
item.Values.Add(value2);
s.Save(value2);
var value3 = new ListingItemValue();
value3.ListingItem = item2;
value3.ListingItemField = field;
item2.Values.Add(value3);
s.Save(value3);
t.Commit();
}
}
static void Work()
{
var s = ObjectFactory.GetInstance<ISession>();
IList<Listing> foo;
using (var t = s.BeginTransaction())
{
foo = s.QueryOver<Listing>()
.Left.JoinQueryOver<ListingItem>(x => x.Items)
.Left.JoinQueryOver<ListingItemValue>(x => x.Values)
.Left.JoinQueryOver<ListingItemField>(x => x.ListingItemField)
.TransformUsing(Transformers.DistinctRootEntity)
.List();
t.Commit();
}
try
{
Thread.Sleep(100);
var x1 = foo[0];
Thread.Sleep(100);
var x2 = x1.Items[0];
Thread.Sleep(100);
var x3 = x2.Values[0];
Thread.Sleep(100);
var x4 = x2.Values[0].ListingItemField.Value;
}
catch (Exception) { }
}
}
}
using (var t = s.BeginTransaction())
{
ListingItem liAlias = null
ListingItemValue livAlias = null;
// 'Preload' all ListingItems with their Values and Fields
s.QueryOver<ListingItem>()
.JoinAlias(li => li.Values, () => livAlias, JoinType.LeftOuterJoin)
.Fetch(_ => livAlias.ListingItemField).Eager
.WithSubquery.WhereProperty(li => li.Id).In(
QueryOver.Of<Listing>()
.Where(l => l.Id == id)
.JoinAlias(l => l.Items, () => liAlias, JoinType.LeftOuterJoin)
.Select(_ => liAlias.Id)
)
.Future();
// Get a single Listing w/ all its Items
var listing = s.QueryOver<Listing>()
.Fetch(l => l.Items).Eager
.Where(l => l.Id == id)
.FutureValue()
.Value;
t.Commit();
}