2013-10-02 7 views
3

를로드하지 않는 모델 첫째,이 같은 엔티티 프레임 워크 설계 (버전 4.4)엔티티 프레임 워크 - 참조 내가 가진

Entity ER diagram 나는 다음과 같은 코드를 사용하여로드 할 때 :

PriceSnapshotSummary snapshot = db.PriceSnapshotSummaries.FirstOrDefault(pss => pss.Id == snapshotId); 

스냅 샷이있다 DataInfo를 제외한 모든 항목 (즉, SnapshotPart, Quote, QuoteType)을로드했습니다. 이제 SQL을 살펴보면 Quote는 0..1의 관계 때문에 DataInfo에 FK가 없기 때문에 나타납니다. 그러나 견적의 'DataInfo'탐색 속성이 여전히 데이터베이스로 가져 와서 가져올 것이라고 예상했을 것입니다.

foreach (var quote in snapshot.ComponentQuotes) 
{ 
    var dataInfo = db.DataInfoes.FirstOrDefault(di => di.Quote.Id == quote.InstrumentQuote.Id); 
    quote.InstrumentQuote.DataInfo = dataInfo; 
} 

이를 달성하기 위해 더 나은 방법이 있나요 : 주위

내 현재 작업이 무엇입니까? EF가 참조를 자동으로로드 할 것이라고 생각했습니다.

+1

'PriceSnapshotSummary snapshot = db.PriceSnapshotSummaries.FirstOrDefault (pss => pss.Id == snapshotId) .Include ("ComponentQuotes.InstrumentQuote.DataInfo"); 또한 실패한 코드를 게시 할 수 있습니까? –

+0

@ NicolásStraubValdivieso 감사합니다! 그랬어. synax에 대한 사소한 수정은 PriceSnapshotSummary입니다. snapshot = db.PriceSnapshotSummaries.Include ("ComponentQuotes.InstrumentQuote.DataInfo"). FirstOrDefault (pss => pss.Id == snapshotId); 관심있는 다른 사람들을 위해. –

+0

그래서 FK가 없다면 엔티티를 기본 엔티티로 로딩하지 않을 것입니다. –

답변

2

이 문제는 기본 linq 빌딩 블록이 Entity Framework와 상호 작용하는 방식과 관련이 있습니다.

는 다음의 (의사) 코드를 가지고 :

IQueryable<Address> addresses; 
Using (var db = new ObjectContext()) { 
    addresses = db.Users.Addresses.Where(addr => addr.Number > 1000); 
} 

addresses.Select(addr => Console.WriteLine(addr.City.Name)); 

이 확인 보이는, 그러나 때문에 된 IQueryable라는 인터페이스의, 런타임 오류가 발생합니다.

IQueryableIEnumerable을 구현하고 표현식 및 제공 업체에 대한 정보를 추가합니다. 이것은 기본적으로 데이터베이스에 대해 sql 문을 작성하고 실행하며 데이터를 가져올 때 전체 테이블을로드 할 필요가 없으며 IEnumerable에서와 같이 반복 실행하지 않아도됩니다.

linq는 사용되기 전까지 표현식 실행을 지연하므로 IQueryable 표현식을 SQL로 컴파일하고 필요할 때만 데이터베이스 쿼리를 실행합니다. 이것은 많은 것을 가속화하고 Where() 또는 Select()이 실행될 때마다 데이터베이스에 가지 않고도 표현 체이닝을 허용합니다. 부작용은 db의 범위 밖에서 객체가 사용되면 db가 처리 된 후에 sql 문이 실행되는 것입니다.

는이 같은 ToList를 사용하여 실행 LINQ를 강제로 :

IQueryable<Address> addresses; 
Using (var db = new ObjectContext()) { 
    addresses = db.Users.Addresses.Where(addr => addr.Number > 1000).ToList(); 
} 

addresses.Select(addr => Console.WriteLine(addr.City.Name)); 

이 DB에 대한 표현을 실행하고 수천보다 큰 숫자로 모든 주소를 얻기 위해 LINQ를 강제 할 것이다. 주소 테이블의 필드에 액세스해야하는 경우이 방법이 모두 좋지만 도시의 이름 (자신과 비슷한 1..1의 관계)을 가져오고 싶기 때문에 다른 범프를 치기 전에 실행합니다. 게으른 로딩.

엔티티 프레임 워크 lazy loads 기본적으로 엔티티이므로 필요한 경우 데이터베이스에서 아무것도 가져 오지 않습니다. 다시 말하지만,이 기능을 사용하면 데이터베이스를 호출 할 때마다 전체 데이터베이스를 메모리에 가져올 수 있기 때문에 작업 속도가 상당히 빨라집니다. 이용 가능한 문맥에 의존하는 문제가있다.

EF를 eager load으로 설정할 수 있습니다 (모델에서 속성으로 이동하여 '지연로드 사용'을 False로 설정)하지만 사용하지 않는 정보가 많습니다.나는 이것이 정말 간단한 예를 들어 알고 있지만, 현실 세계에서 당신은 당신의 의존성을 처리하기 위해 Ninject에 같은 DI 컨테이너를 사용할 수 있습니다

IQueryable<Address> addresses; 
Using (var db = new ObjectContext()) { 
    addresses = db.Users.Addresses.Where(addr => addr.Number > 1000); 
    addresses.Select(addr => Console.WriteLine(addr.City.Name)); 
} 

:

이 문제에 대한 가장 좋은 수정 dB의 범위 내에서 모든 것을 실행하는 것입니다 응용 프로그램을 실행하는 동안 데이터베이스를 사용할 수있게하십시오.

이렇게하면 Include이됩니다. 는 SQL 문을 만들 때에 IQueryable가 지정된 모든 관계의 경로를 포함 할 것입니다 포함 :이 작동

IQueryable<Address> addresses; 
Using (var db = new ObjectContext()) { 
    addresses = db.Users.Addresses.Include("City").Where(addr => addr.Number > 1000).ToList; 
} 

addresses.Select(addr => Console.WriteLine(addr.City.Name)); 

, 그리고 전체 데이터베이스를로드 할 필요와 DI를 지원하는 전체 프로젝트를 리팩토링하는 데 사이 좋은 타협이다.

당신이 할 수있는 또 다른 일은지도 multiple tables to a single entity입니다. 귀하의 경우 관계가 1-0.1이므로 문제가 발생하지 않아야합니다.

+0

DB 컨텍스트가 아직 열려 있는지 확인 했으므로 그 원인이 아닌 것 같습니다. 하지만 분명히 후루에 대해서 알고있는 것이 좋습니다. 또한 데이터베이스 테이블을 분석 할 때이 0..1 관계는 그 방향으로 생성 된 FK가 없음을 의미합니다. 그래서 첫 코멘트가 내 문제를 해결했습니다. 이것이 EF 측의 최적화라고 생각합니다. –

+0

코드를 공유 하시겠습니까? 왜 모델이 먼저 db 컨텍스트와 함께 작동하지 않는지 알고 싶습니다. –

+0

그래, 불필요한 비트를 제거하고 곧 공유 할 것입니다. 감사! –