원자 동작 당 하나의 데이터 콘텍스트와 함께 LINQ에서 SQL을 사용하는 문제

StackOverflow https://stackoverflow.com/questions/259524

문제

다음과 같이 보이는 (비트 DDD 유사) 시스템에서 LINQ에서 SQL을 사용하기 시작했습니다.

public class SomeEntity // Imagine this is a fully mapped linq2sql class.
{
    public Guid SomeEntityId { get; set; }
    public AnotherEntity Relation { get; set; }
}

public class AnotherEntity // Imagine this is a fully mapped linq2sql class.
{
    public Guid AnotherEntityId { get; set; }
}

public interface IRepository<TId, TEntity>
{
    Entity Get(TId id);
}

public class SomeEntityRepository : IRepository<Guid, SomeEntity>
{
    public SomeEntity Get(Guid id)
    {
        SomeEntity someEntity = null;
        using (DataContext context = new DataContext())
        {
            someEntity = (
                from e in context.SomeEntity
                where e.SomeEntityId == id
                select e).SingleOrDefault<SomeEntity>();
        }

        return someEntity;
    }
}

이제 문제가 발생했습니다. 내가 이와 같이 someentityrepository를 사용하려고 할 때

public static class Program
{
    public static void Main(string[] args)
    {
        IRepository<Guid, SomeEntity> someEntityRepository = new SomeEntityRepository();
        SomeEntity someEntity = someEntityRepository.Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));
        Console.WriteLine(someEntity.SomeEntityId);
        Console.WriteLine(someEntity.Relation.AnotherEntityId);
    }
 }

프로그램이 마지막 writeline에 도달 할 때까지 모든 것이 잘 작동합니다. ObjectDisposedException, DataContext가 더 이상 존재하지 않기 때문에.

실제 문제가 보이지만 어떻게 해결해야합니까? 나는 몇 가지 해결책이 있다고 생각하지만, 내가 지금까지 생각한 것들 중 어느 것도 내 상황에서 좋지 않을 것입니다.

  • 저장소 패턴에서 벗어나 작업의 각 원자 부분에 대해 새로운 데이터 컨텍스트를 사용하십시오.
    • 나는 정말로 이것을하고 싶지 않을 것이다. 이유는 저장소를 인식하기 위해 응용 프로그램이되고 싶지 않기 때문입니다. 또 다른 하나는 LINQ2SQL 물건을 보이는 것이 좋을 것이라고 생각하지 않는다는 것입니다.
    • 또한, 나는 그렇게 생각합니다 context.SubmitChanges() 아마도 내가 의도했던 것보다 훨씬 더 많이 저지를 것입니다.
  • 관련 요소를 가져 오기 위해 데이터로드를 지정합니다.
    • 비즈니스 로직 계층이 어떤 경우에도 일부 엔티티와 답장하기를 원하기 때문에 어떤 하위 단점을 사용해야하는지 모르겠습니다.
  • 모든 속성에 대한 게으른 하중/지연 로딩을 비활성화합니다.
    • 옵션이 아닙니다. 테이블이 꽤 많고 크게 연결되어 있기 때문에 옵션이 아닙니다. 이로 인해 많은 불필요한 트래픽 및 데이터베이스로드가 발생할 수 있습니다.
  • 인터넷의 일부 게시물은 .single ()을 사용하면 도움이 될 것이라고 말했습니다.
    • 분명히 그것은 ...

이 불행을 해결할 수있는 방법이 있습니까?

BTW : 우리는 비교적 가벼운 ORM 솔루션이며 .NET Framework 및 Visual Studio에 포함되어 있기 때문에 LINQ T0 SQL을 사용하기로 결정했습니다. .NET 엔티티 프레임 워크 가이 패턴에 더 잘 맞으면 전환하는 옵션 일 수 있습니다. (우리는 아직 구현에 그리 멀지 않습니다.)

도움이 되었습니까?

해결책

Rick Strahl은 데이터 콘텐츠 라이프 사이클 관리에 대한 멋진 기사를 여기에 있습니다. http://www.west-wind.com/weblog/posts/246222.aspx.

기본적으로 원자력 동작 접근 방식은 이론적으로 좋지만 데이터 개체를 추적하고 데이터 개체에서 어린이를 가져올 수 있도록 데이터 컨텍스트를 유지해야합니다.

또한보십시오: LINQ에서 SQL DATACONTEXT의 다중/단일 인스턴스 그리고 LINQ ~ SQL- 데이터 콘텍스트는 어디에 살고 있습니까?.

다른 팁

당신은 다음 중 하나가 필요합니다 :

1) 아직 어떤 데이터를 사용할지 완전히 결정하지 않았기 때문에 컨텍스트를 열어 두십시오 (일명, 게으른 로딩).

또는 2) 다른 속성이 필요하다는 것을 알고 있다면 초기 부하에 대한 더 많은 데이터를 가져옵니다.

후자에 대한 설명 : 여기

원자력 유닛을 사용하면 저장소를 포기해야할지 확신하지 못합니다. 나는 두 가지를 사용하지만, 낙관적 동시성 검사는 어쨌든 계층에서 운동하지 않기 때문에 (타임 스탬프 나 다른 필요한 규칙을 사용하지 않고) 인정합니다. 내가 끝내는 것은 데이터 컨텍스트를 사용하고 완료되면 버리는 저장소입니다.

이것은 관련없는 실버 라이트 예제의 일부이지만, 처음 세 부분은 내가 SQL에서 SQL 컨텍스트에서 SQL 컨텍스트를 사용하여 저장소 패턴을 사용하는 방법을 보여줍니다. fwiw : http://www.dimebrain.com/2008/09/linq-wcf-silver.html

관련 요소를 가져 오기 위해 데이터로드를 지정합니다. 비즈니스 로직 계층이 어떤 경우에도 일부 엔티티와 답장하기를 원하기 때문에 어떤 하위 단점을 사용해야하는지 모르겠습니다.

발신자에게. Relation 속성을 사용하는 데 필요한 커플 링이 부여되면 발신자는 데이터로드 옵션을 지정할 수도 있습니다.

DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Entity>(e => e.Relation);
SomeEntity someEntity = someEntityRepository
  .Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"),
  loadOptions);

//

using (DataContext context = new DataContext())
{
  context.LoadOptions = loadOptions;

이것이 제가하는 일이며 지금까지 정말 잘 작동했습니다.

1) DataContext를 리포지토리에서 멤버 변수로 만듭니다. 그렇습니다. 이것은 당신이 저장소가 이제 idisposable을 구현하고 열려 있지 않아야한다는 것을 의미합니다 ... 어쩌면 당신이하지 않아도되고 싶은 일이지만 불편하다는 것을 알지 못했습니다.

2) 이와 같은 저장소에 몇 가지 방법을 추가하십시오.

public SomeEntityRepository WithSomethingElseTheCallerMightNeed()
{
 dlo.LoadWith<SomeEntity>(se => se.RelatedEntities);
 return this; //so you can do method chaining
}

그런 다음 발신자는 다음과 같습니다.

SomeEntity someEntity = someEntityRepository.WithSomethingElseTheCallerMightNeed().Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));

저장소가 DB에 도달 할 때 해당 도우미 방법에 지정된 데이터로드 옵션을 사용하는지 확인하면됩니다 ... 내 경우 "DLO"는 멤버 변수로 유지 된 다음 DB를 치기 직전에 설정합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top