커미션 추적 시스템에서 작업 중입니다. 비즈니스 사례는 영업 직원과 고객간에 다 대다 관계가 필요합니다. (간체) 엔티티는 다음과 같습니다 순간Entity Framework 다 대다 쿼리가 잘못 생성 됨 SQL
public class Customer {
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<CustomerSeller> CustomerSellers { get; set; }
public virtual ICollection<Payment> Payments { get; set; }
}
public class Seller {
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<CustomerSeller> CustomerSellers { get; set; }
}
// join table w/payload for many-to-many relationship
public class CustomerSeller {
public int Id { get; set; }
public Seller Seller { get; set; }
public Customer Customer { get; set; }
public decimal CommissionRate { get; set; }
}
public class Payment {
public int Id { get; set; }
public Customer ReceivedFrom { get; set; }
public DateTime Date { get; set; }
public decimal Amount { get; set; }
}
내 목표는 주어진 판매 사람에게 연결되어 고객에게 모든 지불의 목록을 얻을 수 있습니다. 이 코드 내 ASP NET MVC 사이트에
select Payment.*
from Payment
inner join CustomerSeller on CustomerSeller.Customer_Id = Payment.ReceivedFrom_Id
where CustomerSeller.Seller_Id = @sellerIdToQuery
내가 LINQ/EF와 함께이 노력하고있어 : 내가 바로 SQL을 작성하는 경우는 다음과 같이 보일 것이다
public ActionResult Sales(int id) {
var qry = (
from p in db.Payments
join cs in db.CustomerSellers on p.ReceivedFrom equals cs.Customer
where cs.Seller.Id == id
select p);
var paymentList = qry.ToList();
return View(paymentList);
}
이 작업을 수행, 하지만 무대 뒤의 SQL은 (는 분석 내 SQL-디코딩 능력을 넘어) waaay 복잡 같습니다
{SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Date] AS [Date],
[Extent1].[Amount] AS [Amount],
[Extent1].[ReceivedFrom_Id] AS [ReceivedFrom_Id]
FROM [dbo].[Payment] AS [Extent1]
INNER JOIN [dbo].[CustomerSeller] AS [Extent2] ON EXISTS (SELECT
1 AS [C1]
FROM (SELECT 1 AS X) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent3].[Id] AS [Id]
FROM [dbo].[Customer] AS [Extent3]
WHERE [Extent1].[ReceivedFrom_Id] = [Extent3].[Id]) AS [Project1] ON 1 = 1
LEFT OUTER JOIN (SELECT
[Extent4].[Id] AS [Id]
FROM [dbo].[Customer] AS [Extent4]
WHERE [Extent2].[Customer_Id] = [Extent4].[Id]) AS [Project2] ON 1 = 1
LEFT OUTER JOIN (SELECT
[Extent5].[Id] AS [Id]
FROM [dbo].[Customer] AS [Extent5]
WHERE [Extent1].[ReceivedFrom_Id] = [Extent5].[Id]) AS [Project3] ON 1 = 1
LEFT OUTER JOIN (SELECT
[Extent6].[Id] AS [Id]
FROM [dbo].[Customer] AS [Extent6]
WHERE [Extent2].[Customer_Id] = [Extent6].[Id]) AS [Project4] ON 1 = 1
WHERE ([Project1].[Id] = [Project2].[Id]) OR (([Project3].[Id] IS NULL) AND ([Project4].[Id] IS NULL))
)
WHERE [Extent2].[Seller_Id] = @p__linq__0}
내 LINQ 쿼리가 (나는 새로운 해요) 심하게 형성되어있는 경우에 특히 관심이 있어요 .. 어떻게 작성해야합니까? 아니면 내 조직의 구조에 문제가 있습니까? 또는 SQL을 사용하면 프로덕션 환경에서 많은 양의 데이터를 효율적으로 실행할 수 있습니까?
는 PROGRESS :는
첫째, Slauma 두 개의 새로운 쿼리를 제안했다. 그들과 함께 실험하면서 SQL은 Customer 테이블과 Seller 필드에 대한 Join 테이블 CustomerSeller에 NULL을 처리하는 데 추가적인 노력을 기울이고 있음을 알았습니다. 이 필드는 null이 허용되지 않아야하므로 내 부분에서 오류가 발생했습니다.
public class CustomerSeller {
public int Id { get; set; }
[Required]
public Seller Seller { get; set; }
[Required]
public Customer Customer { get; set; }
public decimal CommissionRate { get; set; }
}
Slauma가 쓴 첫 번째 질의 : 나는 엔티티의 [필수]로 설정 Slauma 권장
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Date] AS [Date],
[Extent1].[Amount] AS [Amount],
[Extent1].[ReceivedFrom_Id] AS [ReceivedFrom_Id]
FROM [dbo].[Payment] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[CustomerSeller] AS [Extent2]
WHERE ([Extent1].[ReceivedFrom_Id] = [Extent2].[Customer_Id]) AND ([Extent2].[Seller_Id] = @p__linq__0)
)
다음 팅겨했다 :
var qry = from p in db.Payments
where p.ReceivedFrom.CustomerSellers.Any(cs => cs.Seller.Id == id)
select p;
가 생성 훨씬 뛰어난 SQL을 가지고 전체 엔터티가 아닌 Id 필드에서 원래 쿼리에 참여하십시오.
var qry = from p in db.Payments
//old: join cs in db.CustomerSellers on p.ReceivedFrom equals cs.Customer
//new:
join cs in db.CustomerSellers on p.ReceivedFrom.Id equals cs.Customer.Id
where cs.Seller.Id == id
select p;
내가 SQL에 직접 자신을 쓴 것입니다 무슨 본질적으로
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Date] AS [Date],
[Extent1].[Amount] AS [Amount],
[Extent1].[ReceivedFrom_Id] AS [ReceivedFrom_Id]
FROM [dbo].[Payment] AS [Extent1]
INNER JOIN [dbo].[CustomerSeller] AS [Extent2] ON [Extent1].[ReceivedFrom_Id] = [Extent2].[Customer_Id]
WHERE [Extent2].[Seller_Id] = @p__linq__0
:
이 매우 높은 품질의 SQL 문을 생성합니다.
테이크 아웃 :이
(1) 키를 오히려 전체 개체보다 가입.
(2) 조인 테이블이 다 대다 매핑 필드에 대해 null을 가질 수 없으면 [필수]로 표시하여 쿼리를 약간 단순화합니다.
(3) 특히 빈번하게 사용되거나 많은 양의 데이터를 만질 수있는 경우 linq 쿼리를 위해 비하인드 SQL을 확인하십시오. 괴물이 숨어있을 수 있습니다.
(4) 슬라 우마는 신사이자 학자입니다.:-)
내가 쿼리 이런 식으로 작성합니다
솔직히 말해서 그것은 혼란스러워 보입니다. 쿼리 계획과 쓴 쿼리를 보았습니까? 이 밝혀 – Charleh