Sha*_*hin 18 c# structuremap asp.net-mvc entity-framework dependency-injection
假设有一个ASP.NET MVC应用程序使用Entity Framework 6,代码优先方法和StructureMap作为IoC.
它还使用工作单元模式.以下是代码:
域类
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
IUnitOfWork和DbContext:
public interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
}
public class Sample07Context : DbContext, IUnitOfWork
{
public DbSet<Product> Products { set; get; }
#region IUnitOfWork Members
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
服务类中的业务逻辑:
public interface IProductService
{
void AddNewProduct(Product product);
IList<Product> GetAllProducts();
}
public class ProductService : IProductService
{
IUnitOfWork _uow;
IDbSet<Product> _products;
public ProductService(IUnitOfWork uow)
{
_uow = uow;
_products = _uow.Set<Product>();
}
public void AddNewProduct(Product product)
{
_products.Add(product);
}
public IList<Product> GetAllProducts()
{
return _products.Include(x => x.Category).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
在控制器中注入服务类
public class HomeController : Controller
{
private IProductService _productService;
private IUnitOfWork _uow;
public HomeController(IUnitOfWork uow, IProductService productService)
{
_productService = productService;
_uow = uow;
}
[HttpGet]
public ActionResult Index()
{
var list = _productService.GetAllProducts();
return View(list);
}
}
Run Code Online (Sandbox Code Playgroud)
我们在app_start中调用的StructureMap配置:
private static void initStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context());
x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
});
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
Run Code Online (Sandbox Code Playgroud)
单个数据库一切正常,但在我的场景中,用户可以使用多个数据库,我的意思是用户应该能够在运行时更改连接字符串.我们为用户在应用程序中创建的每个项目创建单独的数据库.
现在问题是我们将DbContext注入服务并且DbContext从web.config读取连接字符串,因此当用户更改数据库时,我们无法将新连接字符串设置为DbContext.
你有什么建议?
Joe*_*ang 17
根据我的经验,我使用了Database FirstEF 6中的模式.DbContext当我添加时,将生成如下所示Entity Data Model.
public TestEntities()
: base("name=TestEntities")
{
}
Run Code Online (Sandbox Code Playgroud)
的TestEntities代表ConnectionString在App.config元件
<connectionStrings>
<add name="TestEntities" connectionString="..." providerName="System.Data.EntityClient" />
</connectionStrings>
Run Code Online (Sandbox Code Playgroud)
但您可以将默认代码更改为以下.
public partial class TestEntities : DbContext
{
public TestEntities()
: base("name=TestEntities")
{
}
public TestEntities(string sConnectionString)
: base(sConnectionString)
{
}
...}
Run Code Online (Sandbox Code Playgroud)
所以你有两个选择来获得数据库连接.
使用默认值.EF将在配置文件中找到连接字符串.
将连接字符串传递给DbContext.
代码如下所示.
EntityConnection entityConn =DBConnectionHelper.BuildConnection();
using (var db = new TestEntities(entityConn.ConnectionString))
{
....
}
Run Code Online (Sandbox Code Playgroud)
至于问题How to build a EntityConnection?.请参阅MSDN EntityConnection.
希望它有所帮助.
谢谢.
默认情况下,从DbContext类名称中推断出要在Entity Framework中使用的连接字符串的名称。但是,您可以将连接字符串作为构造函数参数传递:
public class MyDbContext : DbContext, IUnitOfWork
{
public MyDbContext(string connectionString)
: base(connectionString)
{
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以配置StructureMap以传入当前连接字符串,例如
For<IUnitOfWork>().Use(ctx => new MyDbContext(TheConnectionStringToUse));
Run Code Online (Sandbox Code Playgroud)
这可能来自您在代码中设置的静态值,当前会话等。
我将建议一条完全不同的道路。假设您在 web.config 中设置了连接字符串(您说这样做了),为什么不使用 web.debug.config 和 web.release.config 转换来适当地设置连接字符串呢?
即在 web.debug.config 中
<connectionStrings>
<add name="FooEntities" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string="Data Source=IP,PORT\Instancename;
Initial Catalog=Foo;Persist Security Info=True;User ID=admin;Password=password;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient"/>
</connectionStrings>
Run Code Online (Sandbox Code Playgroud)
和一个 web.release.config 本身
<connectionStrings xdt:Transform="Replace">
<add name="FooEntities" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string="Data Source=LIVEIP,PORT\Instancename;
Initial Catalog=Foo;Persist Security Info=True;User ID=admin;Password=password;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient"/>
</connectionStrings>
Run Code Online (Sandbox Code Playgroud)
这里有一个非常详尽的解释
| 归档时间: |
|
| 查看次数: |
36213 次 |
| 最近记录: |