【问题标题】:Querying Child Collections 2 levels deep in LINQ在 LINQ 中查询子集合 2 个级别
【发布时间】:2011-12-16 05:05:05
【问题描述】:

我目前有一个 linq to entity 模型设置如下

每个样本都有一个测试集合 每个测试都有一个结果集合 每个 Result 都有 Status 属性来评估它是可用还是已完成

我将如何编写一个 linq 查询: 获取具有可用结果的样本 只保留有可用结果的测试 并且只有每个测试中的结果可用

无法解决这个问题并帮助解决这个问题 写出来真的很有帮助

类:

public class Sample
{
    public Sample()
    {
        Tests = new List<Test>();
    }

    public          int                     Id              { get; set; }
    public          string                  IdText          { get; set; }
    public          DateTime                SampleDate      { get; set; }
    public          DateTime                LoginDate       { get; set; }
    public          string                  Container       { get; set; }
    public          string                  Product         { get; set; }
    public          string                  Name            { get; set; }
    public          string                  Status          { get; set; }

    public virtual  SamplePoint SamplingPoint { get; set; }
    public virtual  SampleTemplate SampleTemplate { get; set; }
    public virtual  Customer ForCustomer { get; set; }
    public virtual  ICollection<Test> Tests { get; set; }

public class Test
{

    public Test()
    {
        Results = new List<Result>();
    }

    public string Id { get; set; }
    public string Status { get; set; }
    public string Analysis { get; set; }
    public string ComponentList { get; set; }
    public virtual Instrument InstrumentUsed { get; set; }
    public virtual ICollection<Result> Results { get; set; }
    public virtual Sample ForSample { get; set; }
}

public class Result
{
    public string Id { get; set; }
    public string TestNumber { get; set; }
    public string Status { get; set; }
    public string Analysis { get; set; }
    public string ComponentName { get; set; }
    public string Text { get; set; }
    public string Units { get; set; }
    public double Value { get; set; }
    public int OutOfRange { get; set; }
    public DateTime SampledDate { get; set; }
    public DateTime SampleLoginDate { get; set; }
    public string SamplePoint { get; set; }
    public virtual Sample ForSample { get; set; }
    public virtual Test ForTest { get; set; }
}

【问题讨论】:

    标签: c# .net linq asp.net-mvc-3 linq-to-entities


    【解决方案1】:

    如果我了解您的表结构,那么很容易向下查询以获得您感兴趣的结果。

    我整理了一组简单的类来测试结果。

    public static class db
    {
        public static List<Sample> Samples = new List<Sample>();
    }
    
    public class Sample
    {
        public string Name;
        public List<Test> Tests = new List<Test>();
    }
    
    public class Test
    {
        public string Name;
        public List<Result> Results = new List<Result>();
    }
    
    public class Result
    {
        public string Name;
        public string Status;   
    }
    

    而我创建了这组测试数据:

    从这里可以很容易地查询数据到可用的结果:

    var query =
        from s in db.Samples
        from t in s.Tests
        from r in t.Results
        where r.Status == "Available"
        select new { Sample = s.Name, Test = t.Name, Result = r };
    

    这给了我这些数据:

    但这并没有正确地按样本和测试对数据进行分组。

    正确执行此操作的一种方法是创建仅包含可用结果的新 SampleTest 对象,如下所示:

    var query =
        from s in db.Samples
        from rt in (
            from t in s.Tests
            from r in t.Results
            where r.Status == "Available"
            group r by t into rts
            select new Test()
            {
                Name = rts.Key.Name,
                Results = rts.ToList()
            })
        group rt by s into srts
        select new Sample()
        {
            Name = srts.Key.Name,
            Tests = srts.ToList()
        };
    

    这会产生这个结果:

    但是,创建看起来像实际实体但实际上并非来自数据库的对象的新实例可能是不可能或不可取的。可能会意外地将其中一个对象持久化回数据库并清除正确的记录!

    因此,我认为最好的替代方法是创建一个嵌套结构,其中包含未修改的数据库实体,并在保持嵌套结构的同时更适当地包含可用测试!

    方法如下:

    var query =
        from s in db.Samples
        from rt in
            (from t in s.Tests
            from r in t.Results
            where r.Status == "Available"
            group r by t into rts
            select new
            {
                Test = rts.Key,
                AvailableResults = rts.ToArray()
            })
        group rt by s into srts
        select new
        {
            Sample = srts.Key,
            AvailableTests = srts.ToArray()
        };
    

    这会产生:

    使用这些结果,您仍然可以访问未更改的 SampleTest 对象,但所有对象都已被可用结果过滤。

    如果这有帮助,请告诉我。

    【讨论】:

    • 我用班级更新了我的帖子,这样你就可以看到我的班级结构
    • ps 如果我能以流畅的结构获得它并且没有匿名对象,我最后想要的只是一个附有正确数据的 List
    • 根据您的类结构,我的中间查询会很好地满足您的需求。你只需要把它连接起来。
    • @AvidProgrammer - 你问我还是 OP?
    • @Enigmativity - 我在问克里斯,他是否能够用实体框架做到这一点?抱歉,如果它造成了混乱。但答案很有帮助。
    【解决方案2】:

    在没有看到你实际的类结构的情况下,我希望这可以在某种程度上有所帮助:

    var testsWithAvailableResults = from test in dbContext.Tests
                                        select new {
                                            Results = (from result in test.Results where result.Status == "Available")
                                         };
    

    【讨论】:

    • 我需要更高一级的测试是样本的孩子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多