Нужен пример для Entity Framework при регистрации саговых репозиториев с помощью autofac
В документации masstransit есть пример для NHiberbate, есть ли у кого-нибудь такой же пример, но с использованием структуры сущностей (SagaDbContextFactory,SagaDbContext) вместо NHibernate
// не забудьте зарегистрировать репозитории саги (пример для 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()) .Как() .SingleInstance(); builder.RegisterGeneric(TypeOf(NHibernateSagaRepository<>)) .Как (TypeOf(ISagaRepository<>));
2 ответа
Я зарегистрировал мой, как это:
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);
}
}
Вы действительно можете зарегистрироваться 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 может автоматически создать делегат фабрики и внедрить его в конструктор хранилища.