我首先使用单元工作模式和entityFramework代码。现在我想使用Autofac来注册UnitOfWork,Repositories和My dbContext。
这是我的UnitOfWork
代码:
public class UnitOfWork : IUnitOfWork
{
private readonly DbContext _context;
public UnitOfWork(DbContext context)
{
_context = context;
Contact = new ContractRepository(context);
}
public void Dispose()
{
_context.Dispose();
GC.SuppressFinalize(_context);
}
public IContactRepository Contact { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
}
这是我的存储库:
public class Repository<Entity> : IRepository<Entity> where Entity : class
{
protected readonly DbContext _noteBookContext;
public Repository(DbContext noteBookContext)
{
_noteBookContext = noteBookContext;
}
public void Add(Entity entity)
{
_noteBookContext.Set<Entity>().Add(entity);
}
}
这是我的一个存储库:
public class ContractRepository: Repository<Contact>,IContactRepository
{
public ContractRepository(DbContext noteBookContext) : base(noteBookContext)
{
}
public DbContext NotebookContext
{
get
{
return _noteBookContext;
}
}
}
这是我的db上下文类:
public class NoteBookContext:DbContext
{
public NoteBookContext(string connectionstring):base(connectionstring)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ContactConfig());
modelBuilder.Configurations.Add(new PhoneConfig());
modelBuilder.Configurations.Add(new PhoneTypeConfig());
modelBuilder.Configurations.Add(new GroupConfig());
base.OnModelCreating(modelBuilder);
}
public DbSet<Contact> Contacts { get; set; }
public DbSet<Phone> Phones { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<PhoneType> PhoneTypes { get; set; }
}
现在我想用构造函数注册UnitOfWork(像这样的构造函数:)
var uow = new UnitOfWork(new NotebookdbContext("connectionstring"));
请注意,NoteBookContext是我的实体框架模型。
我写注册但我得到错误:
var builder = new ContainerBuilder();
builder.RegisterType<NoteBookContext>()
.As<DbContext>();
builder.RegisterType<UnitOfWork>()
.UsingConstructor(typeof(DbContext))
.As<IUnitOfWork>();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
Container container = builder.Build();
这是我的错误:
Autofac.dll中出现未处理的“Autofac.Core.DependencyResolutionException”类型的异常附加信息:可以使用“DataLayer.NoteBookContext”类型的“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的构造函数都不可用服务和参数:
无法解析构造函数'Void .ctor(System.String)'的参数'System.String connectionstring'。
编辑2:
在Cyril Durand的回答帮助下,我写了以下注册配置:
var builder = new ContainerBuilder();
builder.RegisterType<ConnectionStringProvider>().As<IConnectionStringProvider>();
builder.RegisterType<NoteBookContext>().As<DbContext>().WithParameter((pi, c) => pi.Name == "connectionstring",
(pi, c) => c.Resolve<IConnectionStringProvider>().ConnectionString);
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter(ResolvedParameter.ForNamed<DbContext>("connectionstring"));
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
在我的代码中:
using (var scope = DependencyInjection.Container.BeginLifetimeScope())
{
var ConnectionString = scope.Resolve<IConnectionStringProvider>();
ConnectionString.ConnectionString = "Context";
var uw = scope.Resolve<IUnitOfWork>();
var a =uw.Contact.GetAll();
}
但我又得到了错误:
Autofac.dll中出现未处理的“Autofac.Core.DependencyResolutionException”类型异常
附加信息:在类型'NoteBookContext'上调用构造函数'Void .ctor(System.String)'时抛出异常。
大家能帮帮我吗?
错误消息:
Autofac.dll中出现类型为
Autofac.Core.DependencyResolutionException
的未处理异常附加信息:使用Autofac.Core.Activators.Reflection.DefaultConstructorFinder
类型的DataLayer.NoteBookContext
找到的构造函数都不能使用可用的服务和参数调用:无法解析构造函数
System.String connectionstring
的参数Void .ctor(System.String)
。
告诉您Autofac无法创建NoteBookContext
,因为它无法解析connectionstring
类型的名为String
的参数。
你的NoteBookContext
实现需要一个连接字符串,如果没有你告诉它,Autofac就无法知道它。注册NoteBookContext
时,您必须指定connectionstring:
builder.RegisterType<NoteBookContext>()
.As<DbContext>()
.WithParameter("connectionstring", "XXX");
另一种具有动态分辨率和IConnectionStringProvider
界面的解决方案:
public interface IConnectionStringProvider
{
public String ConnectionString { get; }
}
和注册:
builder.RegisterType<ConnectionStringProvider>()
.As<IConnectionStringProvider>()
.InstancePerLifetimeScope();
builder.RegisterType<NoteBookContext>()
.As<DbContext>()
.WithParameter((pi, c) => pi.Name == "connectionstring",
(pi, c) => c.Resolve<IConnectionStringProvider>().ConnectionString)
.InstancePerLifetimeScope();
没有看到错误就很难分辨。但你不需要使用UsingConstructor
。
//Make DbContext per request, if your app is web app (which has http request).
builder.RegisterType<NoteBookContext>()
.As<DbContext>().WithParameter("connectionstring","ConnectionStringValue").InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
Container = builder.Build();
您是否有理由将连接字符串传递给上下文?为您的unitofwork创建一个接口,并执行以下操作:
public class NoteBookContext:DbContext
{
//Change connectionstring below with the name of your connection string in web.config
public NoteBookContext():base("name=connectionstring")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ContactConfig());
modelBuilder.Configurations.Add(new PhoneConfig());
modelBuilder.Configurations.Add(new PhoneTypeConfig());
modelBuilder.Configurations.Add(new GroupConfig());
base.OnModelCreating(modelBuilder);
}
public DbSet<Contact> Contacts { get; set; }
public DbSet<Phone> Phones { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<PhoneType> PhoneTypes { get; set; }
}
并注册如下:
var builder = new ContainerBuilder();
builder.RegisterType<NoteBookContext>()
.As<DbContext>()
.InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>()
.As<IUnitOfWork>()
.InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
Container container = builder.Build();