选择关系表中第一项具有特定值的所有实体

时间:2016-04-05 06:32:48

标签: c# sql-server entity-framework

我正在使用带有Entity Framework 6.1.3和SQL Server的C#。我有以下实体:

public partial class Contract
{
    public Contract()
    {
        this.Records = new List<Record>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string CreatedBy { get; set; }
    public string ModifiedBy { get; set; }
    public System.DateTime Created { get; set; }
    public virtual ICollection<Record> Records { get; set; }
}

public partial class Record
{
    public Record()
    {
        this.Contracts = new List<Contract>();
    }

    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime? Published { get; set; }
    public int RecordID { get; set; } // Primary key
    public int Version { get; set; } // Primary key
    public virtual ICollection<Contract> Contracts { get; set; }
}

他们有多对多的关系。合同有很多记录,可以发布或不发布记录。发布记录时,版本会增加。

现在,我想选择所有Contract合同Record,其中Version Published设置为某个日期的Name Description和{{1}设置为特定值。我只对最高Version的记录感兴趣,该记录也将Published设置为值。 Published的具体日期并不有趣。

Pseudo:获取最后发布的记录名称==“bar”的合同。

// Table data for Records (Description left out for sake of formatting)

RecordId | Name | Version | Published
1        | Bar  | 1       | 2015-01-01
1        | Foo  | 2       | 2015-02-01
1        | Bar  | 3       | 2015-03-01
1        | Foo  | 4       | 2015-04-01
1        | Bar  | 5       | 2015-05-01
1        | Bar  | 6       | 2015-06-01
1        | Foo  | 7       | 2015-07-01 // I want this one.
1        | Foo  | 8       | NULL // not interesting.

我最初尝试过这个:

var result =    context.Contracts.Where(
                    x =>
                        x.Records.Where(r => r.Published.HasValue)
                            .OrderByDescending(r => r.Version)
                            .FirstOrDefault(r => r.Name == "foo") != null);

但是它实际上只是按版本排序,然后检查是否有任何带有Name == "foo"的项目,而不是具有最高版本的项目也是已发布的,因此排序实际上不会带来任何内容。所以我试过这个:

var result =
    context.Contracts.Where(
        x =>
            x.Records.Where(r => r.Published.HasValue)
                .OrderByDescending(r => r.Version)
                .FirstOrDefault().Name == "foo");

哪个更正确,但现在可能会导致空值异常。我还想检查Description是否有值,这将创建此查询:

var result =
    context.Contracts.Where(
        x =>
            x.Records.Where(r => r.Published.HasValue)
                .OrderByDescending(r => r.Version)
                .FirstOrDefault() != null && 
            x.Records.Where(r => r.Published.HasValue)
                .OrderByDescending(r => r.Version)
                .FirstOrDefault().Name == "foo" &&
            x.Records.Where(r => r.Published.HasValue)
                .OrderByDescending(r => r.Version)
                .FirstOrDefault().Description == "some value");

但它看起来效率不高。还有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以使用FirstOrDefault来限制集合,然后使用Take(1)应用所需的条件,而不是Any

var result = context.Contracts
    .Where(x => x.Records
        .Where(r => r.Published.HasValue)
        .OrderByDescending(r => r.Version)
        .Take(1)
        .Any(r => r.Name == "foo" && r.Description == "some value"));

答案 1 :(得分:0)

您也可以尝试:

.Where(r => r.Published.HasValue && 
               r.Name == "foo" && 
          r.Description == "some value")
.Max(r => r.Version) != null