【问题标题】:How can I query on a composite primary key with Fluent NHibernate and QueryOver?如何使用 Fluent NHibernate 和 QueryOver 查询复合主键?
【发布时间】:2012-01-13 10:25:22
【问题描述】:

我有一个Funds 的列表,每个列表都有一个IDConfigID 和一个CountryID。我需要根据这些 ID 为每个 Fund 选择 FundPerformances

FundPerformance 表有一个复合主键 IDConfigIDCountryID

到目前为止,我已经

perfs = _session.QueryOver<FundPerformance>()
            .Where(xx => xx.ConfigId == _configId)
            .Where(Restrictions.In(Projections.Property<FundPerformance>(t => t.Id), funds.Select(xx => xx.Id).ToArray()))
            .Where(Restrictions.In(Projections.Property<FundPerformance>(t => t.CountryId), funds.Select(xx => xx.CountryId).ToArray()))
            .List<FundPerformance>().ToList();

我认为这不会起作用,因为它选择的是单个字段,而不是复合 ID。

我需要做什么才能正确选择数据?

这是当前的 FundPerformance 映射类:

public class FundPerformanceMap : ClassMap<FundPerformance>
{
    public FundPerformanceMap()
    {
        Id(x => x.Id).Column("FundPerformanceStatistics_FundId");
        Map(x => x.CountryId).Column("FundPerformanceStatistics_FundCountryId");
        Map(x => x.ConfigId).Column("FundPerformanceStatistics_ConfigId");

        Map(x => x.OneMonth).Column("FundPerformanceStatistics_OneMonthBack");
        Map(x => x.ThreeMonth).Column("FundPerformanceStatistics_ThreeMonthBack");
        Map(x => x.YTD).Column("FundPerformanceStatistics_YearToDate");
    }
}

【问题讨论】:

    标签: nhibernate fluent-nhibernate queryover composite-key


    【解决方案1】:

    也许你正在寻找别的东西

    public class Fund
    {
        public virtual int Id { get; set; }
        public virtual Country Country { get; set; }
    
        public virtual Config Config { get; set; }
    
        public virtual IDictionary<Config, FundPerformance> Performances { get; private set; }
        public virtual FundPerformance ActualPerformance { get { return Performances[Config]; } }
    
    }
    
    public class FundPerformance
    {
        public virtual Fund Fund { get; set; }
        public virtual Config Config { get; set; }
    
        public virtual int OneMonth { get; set; }
        public virtual int ThreeMonth { get; set; }
        public virtual int YTD { get; set; }
    }
    
    public class Config
    {
        public virtual int Id { get; set; }
    }
    
    public class FundMap : ClassMap<Fund>
    {
        public FundMap()
        {
            CompositeId()
                .KeyProperty(x => x.Id, "FundId")
                .KeyProperty(x => x.CountryId, "FundCountryId");
    
            HasMany(x => x.Performances)
                .KeyColumns.Add("FundPerformanceStatistics_FundId", "FundPerformanceStatistics_FundCountryId")
                .AsMap(fp => fp.Config)
                .Cascade.AllDeleteOrphan()
                .Component(c =>
                {
                    c.ParentReference(x => x.Fund);
                    c.References(x => x.Config, "FundPerformanceStatistics_ConfigId");
                    c.Map(x => x.OneMonth, "FundPerformanceStatistics_OneMonthBack");
                    c.Map(x => x.ThreeMonth, "FundPerformanceStatistics_ThreeMonthBack");
                    c.Map(x => x.YTD, "FundPerformanceStatistics_YearToDate");
                })
        }
    }
    
    // Query
    var someCountry = session.Load<Country>(5); <- get the Country with id 5 without going to the db (proxy when not already loaded) only to have the reference
    
    var key = new Fund { Id = 1, Country = someCountry }
    var fund = session.Get<Fund>(key);
    var performanceByConfig = fund.Performances[_config];
    

    原答案:

    如果 Fund 有一个复合键,那么 FundPerformance 也应该有一个。另外我认为对 Fund 的引用更像是 OOP:

    public class FundPerformance
    {
        public virtual Fund Fund { get; set; }
    
        public virtual int OneMonth { get; set; }
        public virtual int ThreeMonth { get; set; }
        public virtual int YTD { get; set; }
    }
    

    要么将其映射为组件(因为它看起来像依赖的东西)

    public class FundMap : ClassMap<Fund>
    {
        public FundMap()
        {
            CompositeId()
                .KeyProperty(x => x.Id, "FundId")
                .KeyProperty(x => x.CountryId, "FundCountryId")
                .KeyProperty(x => x.ConfigId, "ConfigId");
    
            HasMany(x => x.Performances)
                .KeyColumns.Add("FundPerformanceStatistics_FundId", "FundPerformanceStatistics_FundCountryId", "FundPerformanceStatistics_ConfigId")
                .Cascade.AllDeleteOrphan()
                .Component(c =>
                {
                    c.ParentReference(x => x.Fund);
                    c.Map(x => x.OneMonth, "FundPerformanceStatistics_OneMonthBack");
                    c.Map(x => x.ThreeMonth, "FundPerformanceStatistics_ThreeMonthBack");
                    c.Map(x => x.YTD, "FundPerformanceStatistics_YearToDate");
                })
        }
    }
    

    或作为具有复合键的实体

    public class FundPerformanceMap : ClassMap<FundPerformance>
    {
        public FundPerformanceMap()
        {
            CompositeId()
                .KeyReference(x => x.Fund, param => param
                    .Column("FundPerformanceStatistics_FundId")
                    .Column("FundPerformanceStatistics_FundCountryId")
                    .Column("FundPerformanceStatistics_ConfigId"));
    
            Map(x => x.OneMonth).Column("FundPerformanceStatistics_OneMonthBack");
            Map(x => x.ThreeMonth).Column("FundPerformanceStatistics_ThreeMonthBack");
            Map(x => x.YTD).Column("FundPerformanceStatistics_YearToDate");
        }
    }
    
    // Query
    var key = new Fund { Id = 1, CountryId = 2, ConfigId = 3}
    var fund = session.Get<Fund>(key);
    var performances = fund.Performances;
    

    【讨论】:

    • 嗨@Firo,谢谢。抱歉,我现在才重新开始,但我今天大部分时间都在忙于其他事情。不过,我有点困惑。您已经说过Fund 应该有一个CompositeId 映射以包含ConfigId。我不确定这是否可行,因为 Fund 表没有 ConfigId 列。它仅在 FundPerformance 中。那行得通吗?或者我可以只指定 ID 和 CountryID 的 Fund CompositeId 映射吗?
    • 你的第一句话“我有一个基金列表,每个基金都有一个 ID、ConfigID 和一个 CountryID。”让我想你有。那么Fundperformance中configId的作用是什么?
    • 对不起 - 我不是故意让它混淆。 FundPerformance 中的 ConfigID 与绩效的计算方式有关。基金有一个属性配置 ID,用于确定它应该选择的性能。
    • 感谢您花在这方面的时间。事实证明,我找到了解决该问题的不同解决方案,因此我无法将您的解决方案标记为正确。不过,我已经投了赞成票,因为它很有帮助,而且您竭尽全力试图提供帮助。谢谢。
    • 然后发布您的解决方案并接受它,以便其他人也可以拥有它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多