Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NHibernate:防止刷新以触发未初始化的集合_C#_Nhibernate_Fluent Nhibernate - Fatal编程技术网

C# NHibernate:防止刷新以触发未初始化的集合

C# NHibernate:防止刷新以触发未初始化的集合,c#,nhibernate,fluent-nhibernate,C#,Nhibernate,Fluent Nhibernate,我有一个具有集合的实体,其中包含对实体有更多引用的其他实体。当实体加载并随后刷新时,将触发延迟加载的集合,并从数据库中提取许多我不需要的内容。那么如何防止刷新触发未初始化的集合呢? 我写了一个小测试来说明这一点 class SimpleClass { public virtual int Id { get; set; } public virtual IList<ChildClass> Childs { get; set; } } class ChildClass

我有一个具有集合的实体,其中包含对实体有更多引用的其他实体。当实体加载并随后刷新时,将触发延迟加载的集合,并从数据库中提取许多我不需要的内容。那么如何防止刷新触发未初始化的集合呢? 我写了一个小测试来说明这一点

class SimpleClass
{
    public virtual int Id { get; set; }

    public virtual IList<ChildClass> Childs { get; set; }
}
class ChildClass
{
    public virtual int Id { get; set; }
}

class SimpleClassMap : ClassMap<SimpleClass>
{
    public SimpleClassMap()
    {
        Id(sc => sc.Id).GeneratedBy.Assigned();

        HasMany(sc => sc.Childs)
            .Cascade.All()
            .LazyLoad();
    }
}
class ChildClassMap : ClassMap<ChildClass>
{
    public ChildClassMap()
    {
        Id(cc => cc.Id).GeneratedBy.Assigned();
    }
}
我在日志中得到了我所期望的,在SQL中删除了别名:

不初始化集合

Session.Get
DEBUG - SELECT Id  FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
Refresh
DEBUG - SELECT Id FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
初始化集合simple.Childs.Count

Session.Get
DEBUG - SELECT Id  FROM "SimpleClass" WHERE Id=:p0;:p0 = 1
simple.Childs.Count();
DEBUG - SELECT SimpleClass_id, Id, Id  FROM "ChildClass" WHERE SimpleClass_id=:p0;:p0 = 1
Refresh
DEBUG - SELECT Id FROM "ChildClass" WHERE Id=:p0;:p0 = 1
DEBUG - SELECT Id FROM "ChildClass" WHERE Id=:p0;:p0 = 2
DEBUG - SELECT Id FROM "ChildClass" WHERE Id=:p0;:p0 = 3
DEBUG - SELECT Id FROM "SimpleClass" WHERE Id=:p0;:p0 = 1

我仍然不确定此操作的其他含义,如果查看为刷新生成的SQL,您将看到它使用左连接而不是第二个查询加载子项,因此它不是延迟加载的,而第一个Get操作没有连接

刷新使用级联设置,并将加载级联设置为“全部”的集合,因此您的问题如下:

HasMany(sc => sc.Childs)
            .Cascade.All()
            .LazyLoad();
如果您编写Cascade.None或Cascade.SaveUpdate,它应该会得到所需的结果。当然,我不知道你是否真的需要Cascade。在这种情况下,我建议将刷新替换为以下内容:

m_session.Evict(simple);
simple = m_session.Get<Order>(1);
编辑:

您可以检查初始化状态并根据该状态进行刷新。不过,这可能不是最好的解决方案

class SimpleClassDAL
{
    [...]
    public void Refresh(ISession session, SimpleClass simple)
    {
        var persistentcollection = simple.Childs as IPersistentCollection;
        if (persistentcollection.WasInitialized)
        {
            // get everything again
            session.Refresh(simple);
        }
        else
        {
            // only refresh simple
            session.Evict(simple);
            simple = session.Get<SimpleClass>(simple.Id);

        }
    }
}

如果查看为刷新生成的SQL,您将看到它使用左联接而不是第二个查询加载子项,因此它不会延迟加载,而第一个Get操作没有联接

刷新使用级联设置,并将加载级联设置为“全部”的集合,因此您的问题如下:

HasMany(sc => sc.Childs)
            .Cascade.All()
            .LazyLoad();
如果您编写Cascade.None或Cascade.SaveUpdate,它应该会得到所需的结果。当然,我不知道你是否真的需要Cascade。在这种情况下,我建议将刷新替换为以下内容:

m_session.Evict(simple);
simple = m_session.Get<Order>(1);
编辑:

您可以检查初始化状态并根据该状态进行刷新。不过,这可能不是最好的解决方案

class SimpleClassDAL
{
    [...]
    public void Refresh(ISession session, SimpleClass simple)
    {
        var persistentcollection = simple.Childs as IPersistentCollection;
        if (persistentcollection.WasInitialized)
        {
            // get everything again
            session.Refresh(simple);
        }
        else
        {
            // only refresh simple
            session.Evict(simple);
            simple = session.Get<SimpleClass>(simple.Id);

        }
    }
}

我已经为现有应用程序实现了DAL。我不能简单地用新获取的实例替换simple,因为我不知道是否还有其他实例需要刷新。@Firo如果我理解正确,您可能需要将刷新逻辑放入DAL中。请参阅我的编辑。不幸的是,可能还有其他对simple的引用,因此我无法将simple切换为新获取的。在我的场景中,我使用了simpleclass 1-lazy->n childclassA 1-nonlazy->n childclassB。刷新似乎总是用所有依赖对象加载simpleclass,而不考虑懒散性,这导致在我的childclassB场景中选择n+1。我切换到lazyload childclassB,这导致了更好的性能,这对我来说已经足够了,尽管我没有解决我的问题,但我接受答案,因为在大多数情况下,您的解决方案都会有所帮助。我已经为现有应用程序实现了DAL。我不能简单地用新获取的实例替换simple,因为我不知道是否还有其他实例需要刷新。@Firo如果我理解正确,您可能需要将刷新逻辑放入DAL中。请参阅我的编辑。不幸的是,可能还有其他对simple的引用,因此我无法将simple切换为新获取的。在我的场景中,我使用了simpleclass 1-lazy->n childclassA 1-nonlazy->n childclassB。刷新似乎总是用所有依赖对象加载simpleclass,而不考虑懒散性,这导致在我的childclassB场景中选择n+1。我切换到lazyload childclassB,这导致了更好的性能,这对我来说已经足够了,虽然我没有解决我的问题,但我接受答案,因为在大多数情况下,您的解决方案会有所帮助。