Linq- 엔티티-SQL“IN”절
T-SQL에서는 다음과 같은 쿼리를 가질 수 있습니다.
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
LINQ to Entities 쿼리에서 어떻게 복제합니까? 가능합니까?
당신이 생각하는 방식으로 머리를 켜야합니다. 미리 정의 된 적용 가능한 사용자 권한 집합에서 현재 항목의 사용자 권한을 찾기 위해 "입력"을 수행하는 대신 현재 항목의 해당 값이 포함되어 있는지 미리 정의 된 사용자 권한 집합을 요구합니다. 이것은 .NET의 일반 목록에서 항목을 찾는 것과 정확히 같은 방법입니다.
LINQ를 사용하여이 작업을 수행하는 방법에는 두 가지가 있습니다. 하나는 쿼리 구문을 사용하고 다른 하나는 메서드 구문을 사용합니다. 본질적으로 그것들은 동일하며 선호도에 따라 상호 교환 적으로 사용될 수 있습니다.
쿼리 구문 :
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
방법 구문 :
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
변수를 할당하는 대신 다음과 같은 익명 호출을 통해 foreach를 수행 할 수 있기 때문에이 인스턴스에서 개인적으로 선호하는 방법은 구문입니다.
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
문법적으로 이것은 더 복잡해 보이며 실제로 무슨 일이 일어나고 있는지 파악하기 위해 람다 식 또는 대리자의 개념을 이해해야하지만, 알 수 있듯이 이것은 코드를 상당량 압축합니다.
그것은 모두 코딩 스타일과 선호도에 달려 있습니다. 내 세 가지 예제 모두 약간 다르게 똑같은 일을합니다.
다른 방법으로는 LINQ를 사용하지 않으며 "where"를 "FindAll"로 바꾸는 동일한 방법 구문을 사용하고 동일한 결과를 얻을 수 있습니다. 이는 .NET 2.0에서도 작동합니다.
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
이것은 당신의 목적으로 충분합니다. 두 컬렉션을 비교하고 한 컬렉션에 다른 컬렉션의 값과 일치하는 값이 있는지 확인합니다.
fea_Features.Where(s => selectedFeatures.Contains(s.feaId))
VS2008 / .net 3.5를 사용하는 경우 Alex James의 팁 # 8 ( http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style)을 참조하십시오. -queries-using-linq-to-entities.aspx
그렇지 않으면 array.Contains (someEntity.Member) 메소드를 사용하십시오.
이 맥락에서 Inner Join으로갑니다. 포함을 사용하면 일치하는 항목이 하나만 있음에도 불구하고 6 번 반복합니다.
var desiredNames = new[] { "Pankaj", "Garg" };
var people = new[]
{
new { FirstName="Pankaj", Surname="Garg" },
new { FirstName="Marc", Surname="Gravell" },
new { FirstName="Jeff", Surname="Atwood" }
};
var records = (from p in people join filtered in desiredNames on p.FirstName equals filtered select p.FirstName).ToList();
포함의 단점
두 개의 목록 객체가 있다고 가정합니다.
List 1 List 2
1 12
2 7
3 8
4 98
5 9
6 10
7 6
포함을 사용하면 목록 2에서 각 목록 1 항목을 검색하여 반복이 49 회 발생한다는 것을 의미합니다 !!!
이것은 LINQ 확장 메소드를 직접 사용하여 in 절을 확인할 수있는 가능한 방법 일 수 있습니다.
var result = _db.Companies.Where(c => _db.CurrentSessionVariableDetails.Select(s => s.CompanyId).Contains(c.Id)).ToList();
또한 Entity Data Model 에 대해 SQL-IN과 비슷한 것을 쿼리하려고했습니다 . 내 접근 방식은 큰 OR 식을 작성하는 문자열 작성기입니다. 정말 못 생겼지 만 지금 당장 갈 수있는 유일한 방법 인 것 같습니다.
이제 다음과 같이 보입니다.
Queue<Guid> productIds = new Queue<Guid>(Products.Select(p => p.Key));
if(productIds.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.ProductId = Guid\'{1}\'", entities.Products.Name, productIds.Dequeue());
while(productIds.Count > 0)
{
sb.AppendFormat(" OR {0}.ProductId = Guid\'{1}\'",
entities.Products.Name, productIds.Dequeue());
}
}
이 컨텍스트에서 GUID 작업 : 위에서 볼 수 있듯이 쿼리 문자열 조각에서 GUID 앞에 "GUID"라는 단어가 항상 있습니다. 이것을 추가하지 않으면 ObjectQuery<T>.Where
다음 예외가 발생합니다.
인수 유형 'Edm.Guid'및 'Edm.String'은이 작업과 호환되지 않습니다. 거의 식 6, 열 14와 같습니다.
MSDN 포럼에서 이것을 발견하면 염두에 두는 것이 도움이 될 수 있습니다.
마티아스
... 모든 것이 좋아질 때 .NET 및 Entity Framework의 다음 버전을 기대합니다. :)
BenAlabaster의 대안 대안
우선 다음과 같이 쿼리를 다시 작성할 수 있습니다.
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
확실히 이것은 더 '말도 안되는'것과 쓰기 어려움이지만 모두 동일하게 작동합니다.
따라서 이런 종류의 LINQ 표현을 쉽게 만들 수있는 유틸리티 방법이 있다면 우리는 사업을 할 것입니다.
유틸리티 메소드를 사용하면 다음과 같이 작성할 수 있습니다.
var matches = ctx.People.Where(
BuildOrExpression<People, string>(
p => p.User_Rights, names
)
);
이렇게하면 다음과 같은 효과가있는 표현식이 작성됩니다.
var matches = from p in ctx.People
where names.Contains(p.User_Rights)
select p;
그러나 더 중요한 것은 실제로 .NET 3.5 SP1에 대해 작동합니다.
이를 가능하게하는 배관 기능은 다음과 같습니다.
public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(
Expression<Func<TElement, TValue>> valueSelector,
IEnumerable<TValue> values
)
{
if (null == valueSelector)
throw new ArgumentNullException("valueSelector");
if (null == values)
throw new ArgumentNullException("values");
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
return e => false;
var equals = values.Select(value =>
(Expression)Expression.Equal(
valueSelector.Body,
Expression.Constant(
value,
typeof(TValue)
)
)
);
var body = equals.Aggregate<Expression>(
(accumulate, equal) => Expression.Or(accumulate, equal)
);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
나는 본질적으로 valueSelector (예 : p => p.User_Rights)를 사용하여 모든 값에 대한 술어 표현식을 작성하고 그 술어를 함께 사용하여 완전한 표현식을 작성한다고 말하는 것 외에는이 방법을 설명하려고하지 않습니다. 술부
실제 예 :
var trackList = Model.TrackingHistory.GroupBy(x => x.ShipmentStatusId).Select(x => x.Last()).Reverse();
List<int> done_step1 = new List<int>() {2,3,4,5,6,7,8,9,10,11,14,18,21,22,23,24,25,26 };
bool isExists = trackList.Where(x => done_step1.Contains(x.ShipmentStatusId.Value)).FirstOrDefault() != null;
진심이야? 당신은 한 번도 사용하지 않은
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
참고 URL : https://stackoverflow.com/questions/857973/linq-to-entities-sql-in-clause
'IT story' 카테고리의 다른 글
IIS7 gzip 사용 (0) | 2020.04.18 |
---|---|
포트 465와 587의 차이점은 무엇입니까? (0) | 2020.04.18 |
`from… import` 대`import .` (0) | 2020.04.18 |
매주 크론 작업을 테스트하는 방법? (0) | 2020.04.18 |
지속 시간에 정수를 곱하는 방법? (0) | 2020.04.18 |