2016-08-12 4 views
2

내가 간단한 DbContext이처럼 보이는이 범위 및 apperently container.RegisterFuncFactory<DbContext, MyDbContext>(Lifestyle.Scoped);DbContext 종속성

public static void RegisterFuncFactory<TService, TImpl>(
    this Container container, Lifestyle lifestyle = null) 
    where TService : class 
    where TImpl : class, TService 
{ 
    lifestyle = lifestyle ?? Lifestyle.Transient; 
    var producer = lifestyle.CreateProducer<TService, TImpl>(container); 
    container.RegisterSingleton<Func<TService>>(producer.GetInstance); 
} 

그러나이 같은 간단한 경우는 불가능합니다 이 메시지 때문에 DbContext

대상 컨텍스트 'MyDbContext'를 구성 할 수 없습니다. 기본 생성자를 추가하거나 IDbContextFactory 구현을 제공하십시오.

은 내가 IDbContextFactory의 생각처럼 정말 해달라고, 그래서 유일한 해결책은 나는 MyDbContext에 종속성을 제거 속성으로 설정하십시오 RegisterFuncFactory 방법을 수정하고 수동으로 컨텍스트를 초기화하는 것입니다 가지고 올 수 :

internal static void RegisterFuncFactory<TService, TImpl>(this Container container, Func<TImpl> instanceProducer, Lifestyle lifestyle = null) where TService : class where TImpl : class, TService 
{ 
    lifestyle = lifestyle ?? Lifestyle.Transient; 
    var producer = lifestyle.CreateProducer<TService>(instanceProducer, container); 
    container.Register<Func<TService>>(() => producer.GetInstance, Lifestyle.Singleton); 
} 

container.RegisterFuncFactory<DbContext, MyDbContext>(() => new MyDbContext 
{ 
    UserContext = container.GetInstance<IUserContext>() 
}, Lifestyle.Scoped); 

우아한 것은 아니지만, 내가 원하는 것을 수행하는 "더 좋은"방법이 있습니까? 나는 문맥에 대한 의존성을 명시 적으로 좋아하지만 가능하지는 않다.

는 오류가에서 오는

UPDATE :

'System.Data.Entity.Migrations.Infrastructure.MigrationsException' 는 EntityFramework.dll에서 발생했지만 사용자 코드

에서 처리되지 않은

이 코드에서 Query 메서드의 return 문은 다음과 같습니다.

internal sealed class EntityFrameworkRepository<TEntity> : IEntityWriter<TEntity>, IEntityReader<TEntity> where TEntity : Entity 
{ 
    private readonly Func<DbContext> _contextProvider; 

    public EntityFrameworkRepository(Func<DbContext> contextProvider) 
    { 
     _contextProvider = contextProvider; 
    } 

    public IQueryable<TEntity> Query() 
    { 
     var context = _contextProvider(); 
     return context.Set<TEntity>().AsNoTracking(); 
    } 

    // Methods removed for brevity 

} 
+0

:

public class MyDbContext : DbContext { private readonly IUserContext _userContext; // For migrations public MyDbContext() : base("DefaultConnectionString") { Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Configuration>()); } // For applications public MyDbContext(IUserContext userContext) : base("DefaultConnectionString") { _userContext = userContext; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { // ... Code removed for brevity base.OnModelCreating(modelBuilder); } } 

는 다음과 같은 구성 루트에 연결되어? EF 마이그레이션? – Steven

+0

예, EntityFramework에서''System.Data.Entity.Migrations.Infrastructure.MigrationsException '오류가 발생했습니다.dll하지만 사용자 코드에서 처리되지 않았습니다'반환 statemenet 동안 여기 :'var context = _contextProvider(); return context.Set () .AsNoTracking();' – janhartmann

+0

@janhartmann'Entity' (제약 조건)이란 무엇입니까? 나는 당신이'class' 제약 조건을 지정해야한다고 생각한다. 왜냐하면 지금은'TEntity'가 허용되지 않는 인터페이스가 될 수 있기 때문이다. –

답변

2

두 번째 (기본) 생성자를 추가하십시오. 이 방법으로 EF 마이그레이션은 명령 줄에서 실행할 때이 생성자를 사용할 수 있지만 응용 프로그램에서 두 번째 생성자를 사용할 수 있습니다.

이 두 번째 생성자를 추가 할 때 DbContext에서 Simple Injector의 자동 배선 기능이 느슨하게되었지만 문제가되지 않아야합니다. 다음과 같이 컨텍스트를 연결하면됩니다.

IUserContext userContext = new AspNetUserContext(); 

container.RegisterSingleton<IUserContext>(userContext); 

var contextProducer = Lifestyle.Scoped.CreateProducer<DbContext>(
    () => new MyDbContext(userContext), 
    container); 

container.RegisterSingleton<Func<DbContext>>(contextProducer.GetInstance); 
+0

스티븐에게 감사 드려요. complication을 위해 싱글 톤 등록을 다음과 같이 변경해야했습니다 : 'container.RegisterSingleton > (() => contextProducer.GetInstance);' – janhartmann

+0

매력처럼 작동했습니다! 솔루션으로 답을 표시하고 다른 솔루션에 대한 답변을 게시합니다 (또는 허용되지 않습니까?). – janhartmann

+0

@janhartmann : 완벽한 솔루션을 게시하는 것이 좋습니다. 더 많은 사람들이 그렇게해야합니다. – Steven

0

이 답변은 나중의 사용자를 위해 표시됩니다. @ 십자가 응답은 정답입니다.

마이그레이션을 지원하면서 DbContext에 종속성을 주입하려면 두 개의 생성자를 사용해야합니다. 하나는 마이그레이션 용이고 다른 하나는 응용 프로그램 용입니다. 당신에게이 메시지를주고있다

public static void RegisterEntityFramework<TContext>(this Container container, Func<TContext> context) where TContext : DbContext 
{ 
    if (container == null) throw new ArgumentNullException(nameof(container)); 

    var contextProducer = Lifestyle.Scoped.CreateProducer<DbContext>(context, container); 
    container.RegisterSingleton<Func<DbContext>>(() => contextProducer.GetInstance); 
} 

var userContext = new AspNetHttpUserContext(); 
var container = new Container(); 
container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(); 
container.RegisterSingleton<IUserContext>(userContext); 
container.RegisterEntityFramework(() => new WayFinderDbContext(userContext)); 
container.Verify();