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

我正在尝试获取变体列表,并且对于每个变体都获取所有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 

变体13个子变量

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

变体23个子变量

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

但是在我的输出中注意到Variant1 CustomSubvariantList Variants 2 subvariants list所有Id as 0

在此处输入图像描述

数据模型:

 public class Variants { public int Id { get; set; } public string Name { get; set; } public string Type { get; set; } public virtual ICollection 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 { get; set; } public virtual ICollection TestOperation1 { get; set; } } public class TestOperation { public int Id { get; set; } public Nullable 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; } } 

查询:

 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() }; 

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

情况1当所有父变体中的子变量名称不同时

变种:

 Id Name Type CategoryId 11 Variant1 Add 1 12 Variant2 Add 1 13 Variant3 Add 1 14 Variant4 Add 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 

预期产量在此处输入图像描述

情况2当所有父变体中的子变量名称相同时:

子变体:

 Id VariantId Name 66 11 Abc 67 11 PQR 68 11 Xyz 70 12 Abc 71 12 PQR 72 12 Xyz 

预期产出

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

这是代码:

  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 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 } ] } ] 

从这里您可以下载示例项目。 这个项目是用你发给我的样本数据库完成的,所以是数据库优先,有些道具或表可能有不同的名字,请在项目中移动代码之前检查一下。

基本上我做了什么:

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

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

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

更新:您的解决方案在一个查询中:

 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() }; 

这是您的查询的“变体”..它提取了每个Variant(s)所有SubVariants ,因为它们在表SubVariants中(通过其自动化的Sql Server Identity Id),不管涉及的TestOperation如何,并避免重复作为您的预期输出。

遗憾的是,不可能始终将所有子变量指定为source和tartget子变量,因为此信息取决于testoperation,实际上testop决定子变量是“source”还是“target”。 因此,如果某些子变量未包含在testoperations记录/实体中,那么它们就不能作为源或目标出现..一种解决方法可能是附加,在返回的匿名类型的“Name”属性旁边,也是“Id SubVar”

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

  public class CustomerVariantDTO { public String Type; public String ParentVariant; public IEnumerable 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 { 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} "); } } }