我正在开发一个N-Tier Web应用程序,该应用程序通过IoC的Simple Injector和通用存储库模式为每个客户端使用一个数据库。
当我尝试更改数据库连接时,我发现注入器在Glopal.asax的Application_Start中运行,在这里我仍然无法确定当前用户是谁来设置连接字符串,我需要在运行时而不是在Application_Start,有什么想法吗?
我的存储库类的样本
public class Repository<T> : IRepository<T> where T : BaseEntity
{
private readonly IDBContext _context;
private IDbSet<T> _entities;
public Repository(IDBContext context)
{
_context = context;
}
private IDbSet<T> Entities
{
get
{
if (_entities == null)
{
_entities = _context.Set<T>();
}
return _entities;
}
}
}
DBContxt类的样本
public class DBContext: DbContext, IDBContext
{
public DBContext()
: base("Name=DbConnectionString")
{
Database.SetInitializer<DBContext>(null);
}
//public DBContext(ConnectionStr connection)
// : base(connection.conn)
//{
// Database.SetInitializer<DBContext>(null);
//}
public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
{
return base.Set<TEntity>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(
type =>
type.BaseType != null && type.BaseType.IsGenericType &&
type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
base.OnModelCreating(modelBuilder);
}
}
首先,这里您将遇到一个严重的问题,因为要执行此操作,您将必须知道每个用户的密码,或者以某种方式使其简单明了。我不确定是否可以做到。如果可以,下面的代码将为您提供一个良好的起点。
如果仍然要执行此操作,则需要一个UserContext服务,该服务从HttpContext返回当前用户。并由此构建您的连接字符串。
这可能或应该看起来像这样:
public interface IUserContext
{
string CurrentUser { get; }
}
public class HttpUserContext : IUserContext
{
public string CurrentUser
{
get { return HttpContext.Current.User.Identity.Name; }
}
}
public class ConnectionStringFactory
{
private readonly IUserContext userContext;
private readonly string partialConnectionString;
public ConnectionStringFactory(
IUserContext userContext,
string partialConnectionString)
{
this.userContext = userContext;
this.partialConnectionString = partialConnectionString;
}
public string GetConnectionString()
{
var builder = new SqlConnectionStringBuilder(partialConnectionString);
builder.UserID = this.userContext.CurrentUser;
return builder.ConnectionString;
}
}
//register like this
var connectionStringFactory = new ConnectionStringFactory(
new HttpUserContext(),
"yourconnectionString");
container.RegisterSingle(connectionStringFactory);
container.RegisterPerWebRequest<YourDbContext>(() =>
{
var connectionFactory = container.GetInstance<ConnectionStringFactory>();
var entityConnectionString = connectionFactory.GetConnectionString;
return new YourDbContext(entityConnectionString);
});
注意:对于实体框架,您可能必须调整ConnectionFactory。
更好的解决方案是将集成安全性与SQL Server结合使用,并让您的AppPool模仿当前用户。
更好的方法是使用单个用户帐户(AppPool身份)连接到数据库,并通过在模型中添加一些额外的表并IAuthorizedRepository
在IRepository
界面顶部添加诸如的内容来控制应用程序内的身份验证。看一下有关此主题的讨论:如何实现基于行的安全性
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句