【问题标题】:Retrieving Navigation Properties with NHibernate Criteria使用 NHibernate 标准检索导航属性
【发布时间】:2015-12-29 06:09:17
【问题描述】:

我想我只是在寻找错误的术语,因为我似乎无法找到一个我相当确定是一个简单问题的答案。

我有两个类/映射(简化);

public class Applications
{
    public int Id {get; set;}
    public string Name {get; set;}
    public ApplicationType {get; set;}
    public IEnumerable<ApplicationProperty> ApplicationProperties {get; set;}
}

public class ApplicationProperties
{
    public int Id {get; set;}
    public int Application_Id {get; set}
    public string Value {get; set;}
}

我正在尝试构建一个 Criteria 类(可能是被误导的),以使我们的代码更具可读性/可重用性,如下所示;

public static class ApplicationsQuery
{
    public static ICriteria GetQuery(ISession session)
    {
        return session.CreateCriteria(typeof(Application));
    }

    public static ICriteria WithType(this ICriteria crit, ApplicationType type)
    {
        crit.Add(
            Restrictions.Eq(
                Projections.ProjectionList().Add(
                    Projections.Property<Application>(a => a.ApplicationType)), type));
        return crit;
    }

    public static ICriteria WithProperties(this ICriteria crit)
    {
        // What goes here?!
    }
}

这样我就可以做类似的事情

ICriteria query = ApplicationsQuery.GetQuery(session).WithType(ApplicationType.GameServer).WithProperties();

我尝试过各种方法,例如;

 DetachedCriteria properties =
            DetachedCriteria.For<Application>()
                .SetProjection(Projections.Property<Application>(a => a.ApplicationProperties));
 return crit.Add(Subqueries.Select(properties));
 // Or this
 return crit.SetFetchMode("ApplicationProperties", FetchMode.Eager);

但我无法填充 ApplicationProperties。
我的测试设置如下所示;

session.Save(new Application("Test Application 1", ApplicationType.GameServer), 1);
session.Save(new Application("Test Application 2", ApplicationType.Manager), , 2);
session.Save(new ApplicationProperty(1, "Test Property"), 1);

编辑 添加映射,因为我觉得它们可能存在问题。

public class ApplicationMapping : ClassMap<Application>
{
    public ApplicationMapping()
    {
        Table("Applications");
        Id(o => o.Id, "Application_Id").GeneratedBy.Assigned();
        Map(o => o.Name).Column("Logical_Name");
        Map(o => o.ApplicationType).Column("Application_Type").CustomType<ApplicationType>();

        HasMany(o => o.ApplicationProperties).KeyColumn("Application_Id").ReadOnly().Cascase.None();
    }
}

public class ApplicationPropertyMapping : ClassMap<ApplicationProperty>
{
    public ApplicationPropertyMapping()
    {
        Table("Application_Properties");
        Id(o => o.Id).GeneratedBy.Identity().Column("Property_Id");
        Map(o => o.ApplicationId).Column("Application_Id");
        Map(o => o.Value).Column("Property_Value");
    }
}

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate nhibernate-criteria


    【解决方案1】:

    更新:我删除了代码

    public class ApplicationsQueryBuilder
    {
        private static readonly IProjection ApplicationTypeProperty = Projections.Property<Application>(a => a.ApplicationType);
    
        private readonly DetachedCriteria _query = DetachedCriteria.For<Application>();
        private bool _withProperties;
        private bool _filteredByCollection;
    
        public ApplicationsQueryBuilder WithType(ApplicationType type)
        {
            _query.Add(Restrictions.Eq(ApplicationTypeProperty, type));
            return this;
        }
    
        public ApplicationsQueryBuilder WithTypes(params ApplicationType[] types)
        {
            var or = Restrictions.Disjunction();
            foreach (var type in types)
            {
                or.Add(Restrictions.Eq(ApplicationTypeProperty, type));
            }
    
            _query.Add(or);
            return this;
        }
    
        public ApplicationsQueryBuilder WithProperties()
        {
            _withProperties = true;
            return this;
        }
    
        public ApplicationsQueryBuilder WithProperty(string name)
        {
            _query.CreateCriteria("ApplicationProperties")
                .Add(Restrictions.Eq("Name", name));
            _filteredByCollection = true;
            return this;
        }
        ...
    
        public ICriteria Create(ISession session)
        {
            if (_withProperties && _filteredByCollection)
            {
                _query.SetProjection(Projections.Id());
                return session.CreateCriteria<Application>()
                    .SetFetchMode("ApplicationProperties", FetchMode.Eager);
                    .Add(Subqueries.PropertyIn("Id", _query));
            }
            else if (_withProperties)
            {
                return _query.GetExecutableCriteria(_session)
                    .SetFetchMode("ApplicationProperties", FetchMode.Eager);
            }
            else
            {
                return _query.GetExecutableCriteria(session);
            }
        }
    }
    

    【讨论】:

    • 我认为这个public IEnumerable&lt;string&gt; ApplicationProperties {get; private set;} 无效。 ApplicationProperties 是一个引用/导航属性,它应该是整个对象,而不仅仅是一个字符串。
    • 你真的需要一个完整的对象吗?对我来说它看起来像一个简单的字符串,NHibernate 支持它。如果您需要地图绘制方面的帮助,请告诉我
    • 是的,我简化了一些。从技术上讲,它是 4 个字符串; NameValueExtendedValue1ExtendedValue2(所有字符串)。我的映射很好,我可以创建一个查询来拉入ApplicationProperties,问题是试图拉入Application以及所有ApplicationProperties
    • 更新了映射问题。我有一种感觉,毕竟它们可能是个问题。
    • 您将 Application 和 ApplicationProperty 用作表中的数据而不是对象。我认为这里发生的事情是您单独保存它们,并且会话将它们缓存在原始未连接状态。 session.Save() 之后的 session.Flush(); session.Clear() 应该可以工作。我建议将 ApplicationProperty 更改为依赖类型,而不是具有自己 Id 的实体。如果需要,我可以发布映射。
    猜你喜欢
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多