編輯我爲這一個問題改寫了整個項目。因此,我重新提出了這個問題。如何避免使用複合鍵的NHibernate N + 1
我希望能夠有效地避免N + 1和笛卡爾連接在第三級上將複合鍵與4級深度實體連接在一起。
我正在尋找這個只在幾個查詢中完成,而不是延遲加載,而不是隻是將所有表連接在一起。
A - (多) - >乙 - (多) - 「ç - (複合材料,單) - > 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.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>();
}
}
}
AppRegistry
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;
});
}
}
}
清單實體:
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; }
}
}
計劃(控制檯):
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) { }
}
}
}
顯示您的嘗試以及。 – gdoron 2012-01-28 20:56:11
添加了我目前正在測試的 – BradLaney 2012-01-30 18:00:33
你需要什麼查詢才能返回 - 一個完全加載的'Listing'或一個完全加載的'ListingItem'? 'Listing'和'ListingItem'是否也有'Id'屬性?你可以發佈'ListingItemValue'的映射嗎? – 2012-02-01 19:05:25