大部分我所需要的答案在這裏找到:
http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/
public partial class MyDBContext
{
public MyDBContext() : base() { }
private MyDBContext(DbConnection connection, DbCompiledModel model) : base(connection, model, contextOwnsConnection: false) { }
private static ConcurrentDictionary<Tuple<string, string>, DbCompiledModel> modelCache
= new ConcurrentDictionary<Tuple<string, string>, DbCompiledModel>();
public static MyDBContext Create(string tenantSchema, DbConnection connection)
{
var compiledModel = modelCache.GetOrAdd
(
Tuple.Create(connection.ConnectionString, tenantSchema),
t =>
{
var builder = new DbModelBuilder();
builder.Conventions.Remove<IncludeMetadataConvention>();
builder.Entity<Location>().ToTable("Locations", tenantSchema);
builder.Entity<User>().ToTable("Users", tenantSchema);
var model = builder.Build(connection);
return model.Compile();
}
);
var context = new FmsDBContext(connection, compiledModel);
if(!string.IsNullOrEmpty(tenantSchema) && !tenantSchema.Equals("dbo", StringComparison.OrdinalIgnoreCase))
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
objectContext.Connection.Open();
var currentUser = objectContext.ExecuteStoreQuery<UserContext>("SELECT CURRENT_USER AS Name", null).FirstOrDefault();
if(currentUser.Name.Equals(tenantSchema, StringComparison.OrdinalIgnoreCase))
{
var executeAs = string.Format("REVERT; EXECUTE AS User = '{0}';", tenantSchema);
objectContext.ExecuteStoreCommand(executeAs);
}
}
return context;
}
}
然後你就可以像這樣訪問架構的信息:
using (var db = MyDBContext.Create(schemaName, dbConn))
{
// ...
}
但是,這實際上繞過了使用數據庫用戶。我仍在研究如何使用數據庫用戶的上下文,而不是隻指定模式名稱。
更新:
我終於在這裏解決了最後一關。的關鍵是以下代碼:
if(!string.IsNullOrEmpty(tenantSchema) && !tenantSchema.Equals("dbo", StringComparison.OrdinalIgnoreCase))
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
objectContext.Connection.Open();
var currentUser = objectContext.ExecuteStoreQuery<UserContext>("SELECT CURRENT_USER AS Name", null).FirstOrDefault();
if(currentUser.Name.Equals(tenantSchema, StringComparison.OrdinalIgnoreCase))
{
var executeAs = string.Format("REVERT; EXECUTE AS User = '{0}';", tenantSchema);
objectContext.ExecuteStoreCommand(executeAs);
}
}
AS命令在連接上發出它被用於執行稍後LINQ到實體命令之前執行。只要連接保持打開狀態,用戶的環境就會保持原樣。在我的數據庫中,租戶的模式名稱和用戶名是相同的。
多次更改用戶的執行上下文將導致錯誤,因此使用快速查詢來確定當前用戶上下文。需要一個小實體類來檢索使用連接的信息:
private class UserContext
{
public string Name { get; set; }
}
DbContext類中沒有以Submit開頭的方法。 – Sparafusile 2012-07-22 17:35:46
'SubmitChanges'來自'LinqToSql'。它幾乎與「LinqToEntities」中的SaveChanges不完全相同 – Silvermind 2012-07-22 18:43:15