master数据库上的查询在DatabaseFirst中抛出UnintentionalCodeFirstException

时间:2016-05-23 08:19:16

标签: c# entity-framework master

为sql server master db创建模型存在巨大问题。 我首先选择了数据库,没有包含任何对象,所以我是一个空模型:

masterModel.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会触发事件OnModelCreating,它在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();
        }

    }

我们在这里:抛出新的UnintentionalCodeFirstException(); 不知何故EF希望在master-db中创建一些东西;即使我们设置全局静态属性,它也不应该是模型本身为空:Database.SetInitializer<masterEntities>(null);

1 个答案:

答案 0 :(得分:0)

在这里找到答案:https://stackoverflow.com/a/26120762/5172266

必须正确填充MetaData:

    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();
}

解释(归功于reckface)

  

您获得的异常是因为当您传递纯SQL连接字符串时,它假定您首先使用Code,因此它调用OnModelCreation事件。当您包含如上所示的MetaData部分时,它告诉EF它是一个完整的EF连接字符串。