Как включить роль приложения SQL через Entity Framework
Сейчас я разрабатываю большое государственное приложение с структурой сущностей. сначала у меня есть одна проблема о включении роли приложения SQL. с ado.net я использую код ниже:
SqlCommand cmd = new SqlCommand("sys.sp_setapprole");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = _sqlConn;
SqlParameter paramAppRoleName = new SqlParameter();
paramAppRoleName.Direction = ParameterDirection.Input;
paramAppRoleName.ParameterName = "@rolename";
paramAppRoleName.Value = "AppRole";
cmd.Parameters.Add(paramAppRoleName);
SqlParameter paramAppRolePwd = new SqlParameter();
paramAppRolePwd.Direction = ParameterDirection.Input;
paramAppRolePwd.ParameterName = "@password";
paramAppRolePwd.Value = "123456";
cmd.Parameters.Add(paramAppRolePwd);
SqlParameter paramCreateCookie = new SqlParameter();
paramCreateCookie.Direction = ParameterDirection.Input;
paramCreateCookie.ParameterName = "@fCreateCookie";
paramCreateCookie.DbType = DbType.Boolean;
paramCreateCookie.Value = 1;
cmd.Parameters.Add(paramCreateCookie);
SqlParameter paramEncrypt = new SqlParameter();
paramEncrypt.Direction = ParameterDirection.Input;
paramEncrypt.ParameterName = "@encrypt";
paramEncrypt.Value = "none";
cmd.Parameters.Add(paramEncrypt);
SqlParameter paramEnableCookie = new SqlParameter();
paramEnableCookie.ParameterName = "@cookie";
paramEnableCookie.DbType = DbType.Binary;
paramEnableCookie.Direction = ParameterDirection.Output;
paramEnableCookie.Size = 1000;
cmd.Parameters.Add(paramEnableCookie);
try
{
cmd.ExecuteNonQuery();
SqlParameter outVal = cmd.Parameters["@cookie"];
// Store the enabled cookie so that approle can be disabled with the cookie.
_appRoleEnableCookie = (byte[]) outVal.Value;
}
catch (Exception ex)
{
result = false;
msg = "Could not execute enable approle proc." + Environment.NewLine + ex.Message;
}
Но независимо от того, сколько я искал, я не мог найти способ реализовать на EF.
Другой вопрос: как добавить роль приложения в конструктор моделей данных Entity?
Я использую приведенный ниже код для выполнения параметра с EF:
AEntities ar = new AEntities();
DbConnection con = ar.Connection;
con.Open();
msg = "";
bool result = true;
DbCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
var d = new DbParameter[]{
new SqlParameter{ ParameterName="@r", Value ="AppRole",Direction = ParameterDirection.Input}
, new SqlParameter{ ParameterName="@p", Value ="123456",Direction = ParameterDirection.Input}
};
string sql = "EXEC " + procName + " @rolename=@r,@password=@p";
var s = ar.ExecuteStoreCommand(sql, d);
При запуске ExecuteStoreCommand эта строка возвращает ошибку:
Роли приложения могут быть активированы только на специальном уровне.
2 ответа
Я делаю это следующим образом (при условии, База данных сначала):
- Я создаю DbContext из БД и называю его MyEntitiesBase
Я наследую от MyEntitiesBase для создания MyEntities с помощью следующего кода:
public partial class MyEntities : MyEntitiesBase { private byte[] appRoleCookie; private void SetAppRole() { try { appRoleCookie = Database.SqlQuery<byte[]>( @" DECLARE @cookie VARBINARY(8000) DECLARE @r INT EXEC sp_setapprole 'user', 'pass', @fCreateCookie = true, @cookie = @cookie OUTPUT SELECT @cookie").First(); } catch { throw new AuthenticationException(); } } private void UnSetAppRole() { bool failed = Database.SqlQuery<bool>("DECLARE @result BIT; EXEC @result = sp_unsetapprole @cookie = " + appRoleCookie.ToHexadecimalString() + "; SELECT @result").First(); if (failed) throw new SecurityException(); } public MyEntities() : base() { Database.Connection.Open(); SetAppRole(); } private bool disposed = false; protected override void Dispose(bool disposing) { if (disposed) return; UnSetAppRole(); Database.Connection.Close(); disposed = true; base.Dispose(disposing); } }
куда ToHexadecimalString
это метод расширения для IEnumerable<byte>
, следующее:
public static class BytesExtensions
{
public static string ToHexadecimalString(this IEnumerable<byte> bytes)
{
return "0x" + string.Concat(bytes.Select(b => b.ToString("X2")));
}
}
И это все. Работает с подключением пула и все. Вы просто используете эту унаследованную версию вместо той, что сгенерирована EF.
По сути, вы вызываете хранимую процедуру.
Entity Framework имеет функциональность для оправдания хранимых процедур. Вот объяснение с видео: http://msdn.microsoft.com/en-us/data/gg699321.aspx
Если вы прокрутите вниз до раздела "Использование функций импорта для сопоставления хранимых процедур", вы найдете ту часть, которая подходит вам.