在为SQL服务器主数据库创建模型时遇到巨大问题。我首先选择了数据库,没有包含任何对象,所以我有一个空模型:
主型号.cs:
*//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------*
masterEntities.cs:
public partial class masterEntities
{
static masterEntities()
{
// don't let EF modify the database schema...
Database.SetInitializer<masterEntities>(null);
}
public masterEntities(string connectionString)
: base(connectionString)
{
}
}
目标是对 master 数据库触发查询,以确定当前用户是否具有 serveradmin 权限(稍后创建新数据库):
public bool UserHasAdminPrivilegesAtDatabaseServer(DatabaseServer databaseServer)
{
var sqlBuilder = new SqlConnectionStringBuilder
{
DataSource = databaseServer.Server,
InitialCatalog = "master",
PersistSecurityInfo = true,
IntegratedSecurity = true,
MultipleActiveResultSets = false,
};
//assumes a connectionString name in .config of MyDbEntities
var entityConnectionStringBuilder = new EntityConnectionStringBuilder
{
Provider = "System.Data.SqlClient",
ProviderConnectionString = sqlBuilder.ConnectionString,
Metadata = "res://*/masterModel.csdl|res://*/masterModel.ssdl|res://*/masterModel.msl",
};
var connstring = entityConnectionStringBuilder.ProviderConnectionString;
using (var context = new masterEntities(connstring))
{
const string sql = "SELECT IS_SRVROLEMEMBER('sysadmin')";//"SELECT IS_SRVROLEMEMBER('sysadmin')";
var a = context.Database.SqlQuery<int>(sql).FirstOrDefault();
return a == 1;
}
}
现在的问题是,EF 触发了事件 OnModelCreateating,该事件在 DatabaseFirst 模式下按如下方式实现:
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class masterEntities : DbContext
{
public masterEntities()
: base("name=masterEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
}
我们在这里:抛出新的无意代码第一异常();不知何故,EF 想在主数据库中创建一些东西;即使我们设置了全局静态属性,它也不应该,模型本身为空:Database.SetInitializer<masterEntities>(null)
;
在这里找到了答案:https://stackoverflow.com/a/26120762/5172266
元数据必须正确填写:
private static string GetConnectionString(string model, string providerConnectionString)
{
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
// var efConnection = new EntityConnectionStringBuilder(@"metadata=res://*/model1.csdl|res://*/model1.ssdl|res://*/model1.msl;provider=System.Data.SqlClient;");
efConnection.Provider = "System.Data.SqlClient";
efConnection.ProviderConnectionString = providerConnectionString;
// based on whether you choose to supply the app.config connection string to the constructor
efConnection.Metadata = string.Format("res://*/correctModel.{0}.csdl|res://*/correctModel.{0}.ssdl|res://*/correctModel.{0}.msl", model);
// Make sure the "res://*/..." matches what's already in your config file.
return efConnection.ToString();
}
解释(功劳归于鲁莽)
您得到的异常是因为当您传递纯 SQL 连接字符串时,它假定您首先使用代码,因此它会调用 OnModelCreation 事件。如上所示包含"元数据"部分时,这会告知 EF 这是一个完整的 EF 连接字符串。