아래의 간단한 예제를 사용하면 Linq를 사용하여 여러 테이블에서 결과를 SQL로 반환하는 가장 좋은 방법은 무엇입니까?
두 개의 테이블이 있다고 가정 해보십시오.
Dogs: Name, Age, BreedId
Breeds: BreedId, BreedName
와 함께 모든 개를 반환하고 싶습니다 BreedName
. 나는 모든 개에게 아무런 문제없이 이와 같은 것을 사용해야합니다.
public IQueryable<Dog> GetDogs()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select d;
return result;
}
그러나 품종이있는 개를 원하고 이것을 시도하면 문제가 있습니다.
public IQueryable<Dog> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
Name = d.Name,
BreedName = b.BreedName
};
return result;
}
이제 컴파일러가 Dogs를 기대하기 때문에 익명의 유형 집합을 반환 할 수는 없지만 사용자 정의 유형을 만들지 않고도 이것을 반환 할 수있는 방법이 있습니까? 아니면 자신의 클래스를 만들고 DogsWithBreedNames
select에서 해당 유형을 지정해야합니까? 아니면 다른 쉬운 방법이 있습니까?
답변
나는이 패턴을 찾는 경향이있다 :
public class DogWithBreed
{
public Dog Dog { get; set; }
public string BreedName { get; set; }
}
public IQueryable<DogWithBreed> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new DogWithBreed()
{
Dog = d,
BreedName = b.BreedName
};
return result;
}
그것은 당신이 여분의 클래스를 가지고 있음을 의미하지만, 빠르고 쉽고 코딩이 쉽고, 쉽게 확장 가능하고 재사용 가능하며 유형 안전합니다.
답변
익명 유형을 반환 할 수 는 있지만 실제로는 그렇지 않습니다 .
이 경우 적절한 유형을 만드는 것이 훨씬 낫습니다. 메서드가 포함 된 형식 내에서만 사용하려는 경우 중첩 형식으로 만듭니다.
개인적으로 C #에서 “명명 된 익명 형식”을 가져 오길 원합니다. 즉 익명 형식과 같은 동작이지만 이름과 속성 선언이 있지만 그게 전부입니다.
편집 : 다른 사람들은 개를 반환 제안 한 다음 속성 경로 등을 통해 품종 이름에 액세스합니다. 이는 완전히 합리적인 접근법이지만 IME를 사용하면 원하는 데이터로 인해 특정 방식으로 쿼리를 수행 한 상황이 발생합니다 사용 – 당신은 그냥 돌아 왔을 때, 그 메타 정보가 손실 IEnumerable<Dog>
– 쿼리가 될 수 있습니다 기대 당신이 (말)를 사용하는 Breed
대신 Owner
등 일부로드 옵션으로 인해,하지만 당신은 잊지 및 기타 속성을 사용하기 시작하면, 앱이 작동 할 수 있지만, 원래 예상했던 것만 큼 효율적이지 않습니다. 물론, 나는 쓰레기 또는 과다 최적화 등을 이야기 할 수 있습니다 …
답변
내 2 센트의 가치를 추가하기 위해 🙂 최근에 익명의 객체를 처리하는 방법을 배웠습니다. .NET 4 프레임 워크를 대상으로 할 때만 사용할 수 있으며 System.Web.dll에 대한 참조를 추가 할 때만 사용할 수 있지만 매우 간단합니다.
...
using System.Web.Routing;
...
class Program
{
static void Main(string[] args)
{
object anonymous = CallMethodThatReturnsObjectOfAnonymousType();
//WHAT DO I DO WITH THIS?
//I know! I'll use a RouteValueDictionary from System.Web.dll
RouteValueDictionary rvd = new RouteValueDictionary(anonymous);
Console.WriteLine("Hello, my name is {0} and I am a {1}", rvd["Name"], rvd["Occupation"]);
}
private static object CallMethodThatReturnsObjectOfAnonymousType()
{
return new { Id = 1, Name = "Peter Perhac", Occupation = "Software Developer" };
}
}
System.Web.dll에 대한 참조를 추가하려면 rushonerok의 조언 을 따라야 합니다. [프로젝트] 대상 프레임 워크가 “.NET Framework 4 클라이언트 프로파일”이 아닌 “.NET Framework 4″인지 확인하십시오.
답변
속임수없이 익명의 유형을 반환 할 수 없습니다.
C #을 사용하지 않는 경우 원하는 유형 (구체적인 유형없이 여러 데이터를 반환)을 Tuple이라고합니다.
여기 에 표시된 것을 사용하여 C # 튜플 구현이 많이 있으며 코드는 다음과 같이 작동합니다.
public IEnumerable<Tuple<Dog,Breed>> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new Tuple<Dog,Breed>(d, b);
return result;
}
그리고 전화 사이트에서 :
void main() {
IEnumerable<Tuple<Dog,Breed>> dogs = GetDogsWithBreedNames();
foreach(Tuple<Dog,Breed> tdog in dogs)
{
Console.WriteLine("Dog {0} {1}", tdog.param1.Name, tdog.param2.BreedName);
}
}
답변
다음과 같이 할 수 있습니다.
public System.Collections.IEnumerable GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
Name = d.Name,
BreedName = b.BreedName
};
return result.ToList();
}
답변
ToList()
먼저 메소드 를 사용 하여 데이터베이스에서 행을 가져온 다음 항목을 클래스로 선택해야합니다. 이 시도:
public partial class Dog {
public string BreedName { get; set; }}
List<Dog> GetDogsWithBreedNames(){
var db = new DogDataContext(ConnectString);
var result = (from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
Name = d.Name,
BreedName = b.BreedName
}).ToList()
.Select(x=>
new Dog{
Name = x.Name,
BreedName = x.BreedName,
}).ToList();
return result;}
따라서 트릭이 먼저ToList()
입니다. 즉시 쿼리하여 데이터베이스에서 데이터를 가져옵니다. 두 번째 요령은 항목을 선택하고 객체 이니셜 라이저 를 사용하여 항목이로드 된 새 객체를 생성하는 것입니다.
도움이 되었기를 바랍니다.
답변
C # 7에서는 이제 tuples!를 사용할 수 있습니다. 결과를 반환하기 위해 클래스를 만들 필요가 없습니다.
다음은 샘플 코드입니다.
public List<(string Name, string BreedName)> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
Name = d.Name,
BreedName = b.BreedName
}.ToList();
return result.Select(r => (r.Name, r.BreedName)).ToList();
}
그래도 System.ValueTuple nuget 패키지를 설치해야 할 수도 있습니다.