2017-02-03 1 views
0

Документации masstransit есть пример для NHiberbate, кто-нибудь имеет то же пример, но с использованием рамки сущности (SagaDbContextFactory, SagaDbContext) вместо NHibernateнужен пример для Entity Framework при регистрации саги репозиториев с autofac

 
// do not forget registering saga repositories (example for NHibernate) 
var mappings = mappingsAssembly 
    .GetTypes() 
    .Where(t => t.BaseType != null && t.BaseType.IsGenericType && 
     (t.BaseType.GetGenericTypeDefinition() == typeof(SagaClassMapping<>) || 
     t.BaseType.GetGenericTypeDefinition() == typeof(ClassMapping<>))) 
    .ToArray(); 
builder.Register(c => new SqlServerSessionFactoryProvider(connString, mappings).GetSessionFactory()) 
    .As<ISessionFactory>() 
    .SingleInstance(); 
builder.RegisterGeneric(typeof(NHibernateSagaRepository<>)) 
    .As(typeof(ISagaRepository<>)); 
+0

Просто откройте проблему на GitHub, и я исправлю это. –

+0

Добавлено: https://github.com/MassTransit/MassTransit/issues/790 –

+0

Это не проблема документации. Одна регистрация экземпляра/сопоставление/репо является простой, но на самом деле это не тот же уровень обобщения, что и NH. –

ответ

1

Я зарегистрировал мое так:

builder.RegisterAssemblyTypes(typeof(SomeType).Assembly).AsImplementedInterfaces().AsSelf(); 

builder.RegisterGeneric(typeof(SagaRepository<,>)).As(typeof(ISagaRepository<,>)); 

builder.RegisterGeneric(typeof(SagaDbContext<,>)); 

А затем реализован SagaRepository интерфейс:

internal class SagaRepository<TSaga, TSagaClassMapping> : EntityFrameworkSagaRepository<TSaga>, ISagaRepository<TSaga, TSagaClassMapping> 
    where TSaga : class, ISaga where TSagaClassMapping : SagaClassMapping<TSaga>, new() 
{ 
    public SagaRepository(
     IWorkerConfiguration workerConfiguration) 
     : base(() => new SagaDbContext<TSaga, TSagaClassMapping>(workerConfiguration.ConnectionStrings["SagaRepository"])) 
    { 
    } 
} 

Для отображений я использую базовый класс:

internal abstract class BaseInstanceStateMap<TInstance> : SagaClassMapping<TInstance>, IInstanceStateMap<TInstance> where TInstance : BaseSagaInstance 
{ 
    protected BaseInstanceStateMap() 
    { 
     this.Property(x => x.CorrelationId); 
     this.Property(x => x.CurrentState).HasMaxLength(64); 

     this.Property(x => x.Initiated).HasColumnType("datetime2").IsRequired(); 
     this.Property(x => x.Created).HasColumnType("datetime2").IsRequired(); 
     this.Property(x => x.StateChanged).HasColumnType("datetime2").IsOptional(); 
    } 
} 

Что я тогда унаследовать для каждого из моих отображений:

internal class ProductIndexingStateMap : BaseInstanceStateMap<ProductIndexingSagaInstance> 
{ 
    public ProductIndexingStateMap() 
    { 
     this.Property(x => x.ProductId); 
     this.Property(x => x.ProductCorrelation); 
     this.Property(x => x.EncryptedConnectionString); 
    } 
} 
0

Вы на самом деле можете зарегистрировать EntityFrameworkSagaRepository<T> как родовое, но это потребует от вас регистрации DbContext. Если вы используете SagaDbContext - у вас не может быть более одной саги в вашем приложении. Единственный способ пойти туда - связать реализацию пользовательского репозитория и SagaDbContext через общие параметры типа, это то, что делает @slinzerthegod в своем примере.

Вы также можете создать свой собственный контекст, который будет регистрировать все типы. Например:

public class AssemblyScanningSagaDbContext : DbContext 
{ 
    readonly Assembly _mappingAssembly; 

    public AssemblyScanningSagaDbContext(Assembly mappingAssembly, string nameOrConnectionString) 
     : base(nameOrConnectionString) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    public AssemblyScanningSagaDbContext(Assembly mappingAssembly, ObjectContext objectContext, bool dbContextOwnsObjectContext) 
     : base(objectContext, dbContextOwnsObjectContext) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    public AssemblyScanningSagaDbContext(Assembly mappingAssembly, DbConnection existingConnection, bool contextOwnsConnection) 
     : base(existingConnection, contextOwnsConnection) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    public AssemblyScanningSagaDbContext(Assembly mappingAssembly, string nameOrConnectionString, DbCompiledModel model) 
     : base(nameOrConnectionString, model) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    public AssemblyScanningSagaDbContext(Assembly mappingAssembly, DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection) 
     : base(existingConnection, model, contextOwnsConnection) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    protected AssemblyScanningSagaDbContext(Assembly mappingAssembly) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    protected AssemblyScanningSagaDbContext(Assembly mappingAssembly, DbCompiledModel model) 
     : base(model) 
    { 
     _mappingAssembly = mappingAssembly; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) => 
     modelBuilder.Configurations.AddFromAssembly(_mappingAssembly); 
} 

Если у вас есть такой класс, вы можете сделать следующее:

builder.Register(c => new AssemblyScanningSagaDbContext(typeof(MySagaMapping).Assembly, 
    connectionString).As<DbContext>(); 
builder.RegisterGeneric(typeof(EntityFrameworkSagaRepository<>)) 
    .As(typeof(ISagaRepository<>)) 
    .SingleInstance(); 
builder.RegisterStateMachineSagas(typeof(MySaga).Assembly); 

Autofac способен автоматически создавать заводскую делегата и введет его в хранилище конструктора.

Here is the scanning context as gist.

Смежные вопросы