使用左连接获得不适当的输出

时间:2016-07-25 08:11:14

标签: c# entity-framework linq left-join

我正在尝试获取变体列表,并且对于每个变体都获得所有subvariants list,无论子变量落在何处 特别Test say 100。这是样本数据:

Id      TestId    SourceSubVariantId   TargetSubVariantId   DiffPerc
114      100           66              67                   100.00
115      100           67              68                   100.00
116      100           70              71                   99.99

对于变体1 我有 3个子变量:

Id=66,Name=Abc
Id=68,Name=Pqr
Id=69,Name=xyz

我有 3个变体2变种

Id=70,Name=lmn
Id=71,Name=xxx
Id=72,Name=hhh

但请注意我的输出中Id as 0 Variants 2 subvariants list Variant1 CustomSubvariantList的所有public class Variants { public int Id { get; set; } public string Name { get; set; } public string Type { get; set; } public virtual ICollection<SubVariants> SubVariants { get; set; } } public class SubVariants { public int Id { get; set; } public int VariantId { get; set; } public string Name { get; set; } public virtual Variants Variants { get; set; } public virtual ICollection<TestOperation> TestOperation { get; set; } public virtual ICollection<TestOperation> TestOperation1 { get; set; } } public class TestOperation { public int Id { get; set; } public Nullable<int> TestId { get; set; } public int SourceSubVariantId { get; set; } public int TargetSubVariantId { get; set; } public decimal DiffPerc { get; set; } public virtual SubVariants SubVariants { get; set; } public virtual SubVariants SubVariants1 { get; set; } public virtual Test Test { get; set; } }

enter image description here

数据模型:

int testId=100;
var query =
      from v in context.Variants 
      where v.Type  == "Add"
      select new
      {
           ParentVariant = v.Name,
           Type = v.Method,
           CustomSubvariantList =
           (
                from svName in context.SubVariants.Select(sv => sv.Name).Distinct()
                join x in
                (
                     from sv in v.SubVariants 
                     from to in sv.TestOperation 
                     where to.TestId == testId
                     orderby sv.Id
                     select new
                     {
                          sv.Name,
                          to.DiffPerc,
                          SourceId = (int?)to.SubVariants.Id,
                          TargetID=(int?)to.SubVariants1.Id
                     }
                 )
                 on svName equals x.Name into g  
                 from x in g.DefaultIfEmpty()
                 orderby x.SourceId
                 select new
                 {
                      SourceId=x.SourceId ?? 0,
                      TargetId=x.TargetID ?? 0,
                      Name = svName,
                      DiffPerc = x.DiffPerc
                 }
             ).ToList()
         };

查询:

Id      Name       Type   CategoryId
11      Variant1    Add     1
12      Variant2    Add     1
13      Variant3    Add     1
14      Variant4    Add     1

更新: 根据评论,这是示例输入和预期输出:

案例1 当所有父变体中的子变体名称不同时

变体

Id     VariantId     Name
66      11           Abc
67      11           PQR
68      11           Xyz

70      12           lmn
71      12           xxx
72      12           hhh

子变体:

Id      TestId    SourceSubVariantId   TargetSubVariantId   DiffPerc
114      100           66               67                  10.00
115      100           67               68                  20.00

114      100           70               71                  40.00
115      100           71               72                  50.00

测试操作:

Id     VariantId     Name
66      11           Abc
67      11           PQR
68      11           Xyz

70      12           Abc
71      12           PQR
72      12           Xyz

预期输出enter image description here

案例2 当所有父母变体中的子变体名称相同时:

子变体:

var canRefresh = true

override func scrollViewDidScroll(scrollView: UIScrollView) {

    if scrollView.contentOffset.y < -100 { //change 100 to whatever you want

        if canRefresh && !self.refreshControl.refreshing {

            self.canRefresh = false
            self.refreshControl.beginRefreshing()

            self.refresh() // your viewController refresh function
        }
    }else if scrollView.contentOffset.y >= 0 { 

        self.canRefresh = true
    }
}

预期输出

2 个答案:

答案 0 :(得分:6)

我们有一些关于聊天的讨论,直到我明白你想要什么。

这是代码:

    class Program
{
    static void Main(string[] args)
    {
        VariantsEntities db=new VariantsEntities();

        var queryResult = db.Variants.AsEnumerable().Select(x => new PageViewModel
        {
            ParentVariant = x.Name,
            Type = x.Type,
            CustomSubvariantList = GetCustomSubVariants(x.Id,db).ToList()
        }).ToList();


        var jsonObj = JsonConvert.SerializeObject(queryResult);
        Console.WriteLine(jsonObj);
        Console.ReadKey();
    }

    private static IEnumerable<Customsubvariantlist> GetCustomSubVariants(int variantId, VariantsEntities db)
    {
        var subVariants = db.SubVariants.ToList();

        foreach (var subVariant in subVariants)
        {
            var obj=new Customsubvariantlist();
            obj.Name = subVariant.Name;

            var testOpTarget = db.TestOperations
                .FirstOrDefault(x => x.TargetSubVariantId == subVariant.Id);
            var testOpSource = db.TestOperations
                .FirstOrDefault(x => x.SourceSubVariantId == subVariant.Id);

            if (subVariant.VariantId == variantId)
            {
                obj.Value = testOpTarget == null ? 
                    testOpSource?.SourceValue : testOpTarget?.TargetValue;
                obj.DiffPerc = testOpTarget?.DiffPerc;
            }
            else
            {
                obj.Value = null;
                obj.DiffPerc = null;
            }
            yield return obj;
        }

    }
}

您只需要替换DbContext名称并进行测试即可。

这是结果:

    [
  {
    "ParentVariant": "Variant1",
    "Type": "Add",
    "CustomSubvariantList": [
      {
        "Name": "Abc",
        "Value": 200,
        "DiffPerc": null
      },
      {
        "Name": "Pqr",
        "Value": 300,
        "DiffPerc": 100.0
      },
      {
        "Name": "xyz",
        "Value": 500,
        "DiffPerc": 200.0
      },
      {
        "Name": "lmn",
        "Value": null,
        "DiffPerc": null
      },
      {
        "Name": "xxx",
        "Value": null,
        "DiffPerc": null
      },
      {
        "Name": "hhh",
        "Value": null,
        "DiffPerc": null
      }
    ]
  },
  {
    "ParentVariant": "Variant2",
    "Type": "Add",
    "CustomSubvariantList": [
      {
        "Name": "Abc",
        "Value": null,
        "DiffPerc": null
      },
      {
        "Name": "Pqr",
        "Value": null,
        "DiffPerc": null
      },
      {
        "Name": "xyz",
        "Value": null,
        "DiffPerc": null
      },
      {
        "Name": "lmn",
        "Value": 1000,
        "DiffPerc": null
      },
      {
        "Name": "xxx",
        "Value": 2000,
        "DiffPerc": 1000.0
      },
      {
        "Name": "hhh",
        "Value": 4000,
        "DiffPerc": 2000.0
      }
    ]
  }
]

here您可以下载示例项目。这个项目是使用您发送给我的示例数据库完成的,因此是数据库优先,并且某些道具或表可能具有不同的名称,请在移动项目中的代码之前检查这个。

基本上我做了什么:

  1. 创建了一个新的控制台应用项目

  2. 我从你的json对象中获取了模型(我复制了json对象并将其放在一个类中,使用(vs菜单)Edit - &gt; Past Special - &gt; Past JSON as Classes。

  3. 由于您希望每个SubVariants都有Varian,因此我创建了一个单独的方法来处理您创建CustomSubVariantList的规则。在这个方法中,我迭代抛出所有SubVariants,我根据你的条件创建了对象。

  4. 在一个查询中

    更新您的解决方案:

    static void Main(string[] args)
        {
            VariantsEntities db = new VariantsEntities();
    
            var result = from x in db.Variants                        
                         select new PageViewModel
                         {
                             ParentVariant = x.Name,
                             Type = x.Type,
                             CustomSubvariantList = (from z in db.SubVariants
                                                     let testOpTarget=z.TestOperations1
                                                            .FirstOrDefault(q=>q.TargetSubVariantId==z.Id)
                                                     let testOpSource=z.TestOperations
                                                            .FirstOrDefault(q=>q.SourceSubVariantId==z.Id)
                                                     select new Customsubvariantlist
                                                     {
                                                         Name = z.Name,
                                                         Value = x.Id==z.VariantId? 
                                                                 testOpTarget.TargetValue??
                                                                 testOpSource.SourceValue:null,
                                                         DiffPerc = x.Id==z.VariantId? 
                                                                    testOpTarget.DiffPerc:null
                                                     }).ToList()
                         };
    
            var json = JsonConvert.SerializeObject(result.ToList());
            Console.WriteLine(json);
            Console.ReadKey();
        }
    

    此查询产生与上述方法相同的结果。 如果您需要,请告诉我!!

    更新:这是案例2的查询

     var result = from x in db.Variants
                select new PageViewModel
                {
                    ParentVariant = x.Name,
                    Type = x.Type,
                    CustomSubvariantList = (from z in db.SubVariants.GroupBy(g => g.Name)
                        .Select(g => g.FirstOrDefault(d => d.VariantId == x.Id) ?? g.FirstOrDefault())
                        let testOpTarget = z.TestOperations1
                            .FirstOrDefault(q => q.TargetSubVariantId == z.Id)
                        let testOpSource = z.TestOperations
                            .FirstOrDefault(q => q.SourceSubVariantId == z.Id)
                        select new Customsubvariantlist
                        {
                            Name = z.Name,
                            SubVariantId = z.Id,
                            CombineName =(z.TestOperations.Any() || z.TestOperations1.Any())? 
                                          testOpTarget.TargetValue.HasValue? 
                                          testOpTarget.SubVariant.Name+" to "+testOpTarget.SubVariant1.Name : null: "Undefined",
                            Value = x.Id == z.VariantId
                                ? testOpTarget.TargetValue ??
                                  testOpSource.SourceValue
                                : null,
                            DiffPerc = x.Id == z.VariantId
                                ? testOpTarget.DiffPerc
                                : null
                        }).OrderBy(k => k.SubVariantId).ToList()
                };
    

答案 1 :(得分:3)

这是&#34;变种&#34;您的查询..它提取所有SubVariantsVariant(s)订购,因为它们在表SubVariants(通过其自动化的Sql Server标识ID),无论涉及TestOperation,并避免重复作为您的预期产出。

不幸的是,不可能总是将所有子变量指定为source和tartget子变量,因为这些信息取决于testoperation,实际上testop决定子变量是否为&#34; source&#34;或&#34;目标&#34;。因此,如果某些子变量未被包含在测试操作记录/实体中,那么它们就不能作为源或目标出现..一种解决方法可能是附加,&#34; Name&#34;返回的匿名类型的属性,也是&#34; Id SubVar&#34;

我添加了2个DTO,因为实体框架不允许使用distinct().ToList()方法来保留顺序并应用自定义的不同规则,所以我添加了一个步骤,通过dto从链接到EF传递到链接到对象对象以这种方式使得应用不同的自定义规则成为可能。

    public class CustomerVariantDTO
    {
        public String Type;
        public String ParentVariant;
        public IEnumerable<CustomerSubVariantDTO> CustomSubvariantList;
    }

    public class CustomerSubVariantDTO
    {
        public int? VariantId;
        public int? SubVariantId;
        public int? SourceId;
        public int? TargetId;
        public String Name;
        public Decimal? DiffPerc;
    }

    sealed class CustomerSubVariantDTOComparer : IEqualityComparer<CustomerSubVariantDTO>
    {
        public int GetHashCode(CustomerSubVariantDTO obj)
        {
            return 0;
        }

        public bool Equals(CustomerSubVariantDTO x, CustomerSubVariantDTO y)
        {
            return x.SourceId == y.SourceId &&
                   x.TargetId == y.TargetId &&
                   x.Name == y.Name &&
                   x.DiffPerc == y.DiffPerc;

        }
    }


    public void DoTestOfCustomerVariantDTO()
    {
        int testId = 1;
        using (var context = new VariantsEntities())
        {
            var query =
              (from v in context.Variants
               where v.Type == "Add"
               select new CustomerVariantDTO
               {
                   ParentVariant = v.Name,
                   Type = v.Type,
                   CustomSubvariantList =
                   (
                     from sv in context.SubVariants.Select(sv => sv)
                     join x in
                     (
                         from svparent in v.SubVariants
                         from to in svparent.TestOperation
                         where to.TestId == testId
                         select new
                         {
                             svparent.Name,
                             to.DiffPerc,
                             SourceId = (int?)to.SubVariants.Id ?? 0,
                             TargetId = (int?)to.SubVariants1.Id ?? 0
                         }
                     )
                     on sv.Name equals x.Name into g
                     from x in g.DefaultIfEmpty()
                     select new CustomerSubVariantDTO{
                         VariantId = sv.VariantId,
                         SubVariantId = sv.Id,
                         SourceId = (int?)x.SourceId ?? sv.TestOperation.Select(to => to.SourceSubVariantId).FirstOrDefault(),
                         TargetId = (int?)x.TargetId ?? sv.TestOperation.Select(to => to.TargetSubVariantId).FirstOrDefault(),
                         Name = sv.Name,
                         DiffPerc = x.DiffPerc
                     }
                  ).OrderBy(csv => new { csv.VariantId, csv.SubVariantId })
               }).ToList();

            var listCustomVariants =
                query.Select(v => new{
                    Type = v.Type,
                    ParentVariant = v.ParentVariant,
                    CustomSubvariantList = v.CustomSubvariantList.Distinct(new CustomerSubVariantDTOComparer()).ToList()
                });

            foreach (var item in listCustomVariants){
                Console.WriteLine($"Type: {item.Type} - ParentVariant: {item.ParentVariant} ");
                foreach (var csubvar in item.CustomSubvariantList)
                    Console.WriteLine($"SourceId: {csubvar.SourceId} - TargetiId: {csubvar.TargetId} - NAme: {csubvar.Name} - DiffPerc: {csubvar.DiffPerc} ");
            }
        }
    }