2017-09-28 22 views
1

테이블을Linq에서 병합으로 왼쪽 결합을 수행하는 방법은 무엇입니까?

  • 발명, 발명의 목록을 고려
  • 구성 요소, 발명에서 사용할 수있는 모든 구성 요소의 목록 및 발명의
  • InventionComponents, 카운트 사용되는 구성 요소의 목록,

해당 발명에 대해 & inventID, 왼쪽에 '커버링'을하고 싶습니다. 모든 구성 요소가 대신에 uti lized 구성 요소.

SQL 예외에 https://dotnetfiddle.net/cx4bHp 결과에서 .NET 바이올린에

select 
    I.name as inventionName 
, C.name as componentName 
, coalese (IC.count, 0) as componentCount 
from 
    (select &inventionID as inventionID, ID, name from components) C -- all components applied to some &inventionID 
left join 
    inventionComponents IC 
on 
    C.ID = IC.ComponentID 
    and C.inventionID = IC.inventionID 
join 
    inventions I 
on 
    I.ID = C.inventionID 

샘플 데이터와 LINQ 쿼리 같은 것

[System.NullReferenceException: Object reference not set to an instance of an object.] 

질문 : LINQ 쿼리는을 수행하기 위해 수정해야하는 방법 원하는 커버 리지 쿼리?

완전성 들어, C# 바이올린 코드 DefaultIfEmpty()를 첨가함으로써 여기

using System; 
using System.Collections.Generic; 
using System.Linq; 

public class Program 
{ 
    public static void Main() 
    { 
    var components = new List<Component>{ 
     new Component { ID=1, Name = "Florgebit" }, 
     new Component { ID=2, Name = "Phadron" }, 
     new Component { ID=3, Name = "Goobstem" }, 
     new Component { ID=4, Name = "Larchwren" }, 
     new Component { ID=5, Name = "Zangponder" }, 
     new Component { ID=6, Name = "Spoofork" }, 
     new Component { ID=7, Name = "Forkoon" }, 
     new Component { ID=8, Name = "Blidget" }, 
     new Component { ID=9, Name = "Wazzawim" }, 
     new Component { ID=10, Name = "Klackberg" }, 
    }; 
    var inventions = new List<Invention>{ 
     new Invention { ID=21, Name = "Swazzlute" }, 
     new Invention { ID=22, Name = "Corpocran" }, 
     new Invention { ID=23, Name = "Fillyboof" }, 
    }; 
    var inventionComponents = new List<InventionComponent>{ 
     new InventionComponent { ID=100, InventionID=21, ComponentID=1, Count=1 }, 
     new InventionComponent { ID=101, InventionID=21, ComponentID=2, Count=2 }, 
     new InventionComponent { ID=102, InventionID=21, ComponentID=8, Count=3 }, 
     new InventionComponent { ID=103, InventionID=23, ComponentID=5, Count=4 }, 
     new InventionComponent { ID=104, InventionID=23, ComponentID=6, Count=5 }, 
     new InventionComponent { ID=105, InventionID=23, ComponentID=3, Count=4 }, 
     new InventionComponent { ID=106, InventionID=21, ComponentID=4, Count=3 }, 
     new InventionComponent { ID=107, InventionID=22, ComponentID=5, Count=2 }, 
     new InventionComponent { ID=108, InventionID=22, ComponentID=4, Count=1 }, 
     new InventionComponent { ID=109, InventionID=22, ComponentID=1, Count=6 }, 
     new InventionComponent { ID=110, InventionID=22, ComponentID=7, Count=1 }, 
     new InventionComponent { ID=111, InventionID=21, ComponentID=9, Count=1 }, 
    }; 

    var details = 
     from A in inventions 
     join B in inventionComponents on A.ID equals B.InventionID 
     join C in components on B.ComponentID equals C.ID 
     orderby A.Name, C.Name 
     select new { 
     InventionName = A.Name, 
     ComponentName = C.Name, 
     ComponentCount = B.Count 
     }; 
/* 
    foreach(var d in details) 
    { 
     Console.WriteLine("Invention: {0}, Component: {1}, Count: {2}", d.InventionName, d.ComponentName, d.ComponentCount); 
    } 
*/ 
    var inventionID = 22; 
    var index = 1; 

    // want full coverage of inventionID, componentID with applied counts 
    // 22,1,6 
    // 22,2,**0** 
    // 22,3,**0** 
    // 22,4,1 
    // 22,5,2 
    // 22,6,**0** 
    // 22,7,1 
    // 22,8,**0** 
    // 22,9,**0** 
    // 22,10,**0** 

    var corpcheck = 
     from C in components select new { InventionID = inventionID, ComponentID = C.ID, ComponentName = C.Name } into allcomps 
     join B in inventionComponents on new { allcomps.InventionID, allcomps.ComponentID } equals new { B.InventionID, B.ComponentID } into join1 
     // from j1 in Join1 // inner join 
     from j1 in join1.DefaultIfEmpty() // causes exception 
     orderby allcomps.ComponentName 
     select new { 
      RowNum = index++, 
     InventionID = allcomps.InventionID, 
     ComponentName = allcomps.ComponentName, 
     ComponentCount = j1.Count, 
     }; 


    foreach(var x in corpcheck) 
    { 
     Console.WriteLine("InventionID: {0}, RowNum: {1}, ComponentName: {2}, Count: {3}", x.InventionID, x.RowNum, x.ComponentName, x.ComponentCount); 
    } 
    } 

    public class Invention 
    { 
    public int ID { get; set; } 
    public string Name { get; set; } 
    } 

    public class InventionComponent 
    { 
    public int ID { get; set; } 
    public int InventionID { get; set; } 
    public int ComponentID { get; set; } 
    public int Count { get; set; } 
    } 

    public class Component 
    { 
    public int ID { get; set; } 
    public string Name { get; set; } 
    } 
} 

답변

2

반복, j1 일부 구성 요소에 대한 널이 될 수있다. j1가 null의 경우, 나는 당신이 0으로 계산한다고 가정 :

LINQ - 투 - 객체에서
from C in components select new { InventionID = inventionID, ComponentID = C.ID, ComponentName = C.Name } into allcomps 
    join B in inventionComponents on new { allcomps.InventionID, allcomps.ComponentID } equals new { B.InventionID, B.ComponentID } into join1 
    from j1 in join1.DefaultIfEmpty() 
    orderby allcomps.ComponentName 
    select new { 
     RowNum = index++, 
     InventionID = allcomps.InventionID, 
     ComponentName = allcomps.ComponentName, 
     ComponentCount = j1 == null ? 0 : j1.Count, // add null check 
    }; 

당신은 또한 ComponentCount = j1?.Count ?? 0을 사용할 수 있습니다. 하지만 난 당신이 SQL 백엔드에 LINQ에서 이것을 사용한다고 가정합니다.