gpt4 book ai didi

nhibernate - 如何避免 NHibernate N+1 使用复合键

转载 作者:行者123 更新时间:2023-12-03 12:44:56 26 4
gpt4 key购买 nike

编辑 我为这个问题重新制作了整个项目。因此,我重新提出了这个问题。

我希望能够有效地避免 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.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>();
}
}
}

应用程序注册表
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) { }
}
}
}

最佳答案

您能否提供您的映射的详细信息。减少查询数量(不是一个,而是很少)的一种方法是在映射中使用批量大小功能。这将以比 N+1 更少的往返次数填充代理。但实际上应该有一个解决方案来使用 future 或类似的方式获取所有数据,所以请提供映射。

关于nhibernate - 如何避免 NHibernate N+1 使用复合键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9042078/

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