Это пример реализации ответа, предложенного @TheCloudlessSky.Я думал, что это поможет любому, кто интересуется, как его реализовать.
Я работал с существующей базой данных, поэтому базовый класс модели был сгенерирован для меня автоматически.
Автосгенерированный User.cs:
namespace MyApp.Model
{
public partial class User
{
public int UserId { get; set; }
public byte[] SSN { get; set; }
...
}
}
Я создал свой собственный User.cs.(Обратите внимание, что он находится в том же пространстве имен, что и автоматически сгенерированный файл User.cs, и ошибок компилятора не было, поскольку автоматически созданный файл User.cs был объявлен как частичный класс ! Кроме того, мой собственный файл User.cs не может быть вта же папка, что и автоматически сгенерированный файл User.cs из-за конфликта имен файлов!)
namespace MyApp.Model
{
public partial class User
{
public string DecryptedSSN { get; set; }
...
}
}
Теперь, когда бы мне ни пришлось получить User из моего DbContext, я буду видеть все свойства, определенные в автоматически сгенерированном классе, кака также те, которые определены в моем расширенном классе.
Вот реализация моего UserRepository.cs:
namespace MyApp.Model
{
public interface IUserRepository
{
User Get(int userId);
...
}
public class UserRepository : IUserRepository
{
public User GetById(int userId)
{
using (var dataContext = MyDbContext())
{
var user = dataContext.Users.Find(u => u.UserId == userId);
var decryptedSSNResult = dataContext.Decrypt(u.SSN);
user.DecryptedSSN = decryptedSSNResult.FirstOrDefault();
return user;
}
}
}
}
Теперь вы можете задаться вопросом, откуда / откуда я взял MyDbContext.Decrypt () из?
Это не сгенерировано автоматически для вас.Однако вы можете импортировать эту хранимую процедуру в автоматически созданный файл Model.Context.cs.(Этот процесс очень хорошо задокументирован в официальной статье EntityFramework: Как: импортировать хранимую процедуру (инструменты модели данных Entity) в http://msdn.microsoft.com/en-us/library/vstudio/bb896231(v=vs.100).aspx)
на тот случай, если вы не знаете, как должен выглядеть конечный результат, вот что было автоматически сгенерировано в моем Model.Context.cs:
namespace MyApp.Model
{
// using statements found here
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name = MyDbContext")
{ }
public virtual ObjectResult<string> Decrypt(byte[] encryptedData)
{
var encryptedDataParameter = encryptedData != null ?
new ObjectParameter("encryptedData", encryptedData) :
new ObjectParameter("encryptedData", typeof(byte[]));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<string>("Decrypt", encryptedDataParameter);
}
// similar function for Encrypt
}
}
Вот как выглядит моя хранимая процедура расшифровки:
CREATE PROCEDURE decrypt
@encryptedData VARBINARY(8000)
AS
BEGIN
OPEN SYMMETRIC KEY xxx_Key DECRYPTION BY CERTIFICATE xxx_Cert;
SELECT CAST(DECRYPTIONBYKEY(@encryptedData) AS NVARCHAR(MAX)) AS data;
CLOSE ALL SYMMETRIC KEYS;
END;
GO
ПроизводительностьСоображения
Теперь, когда я показал вам реализацию ответа, данного @TheCloudlessSky, я хотел бы быстро выделить некоторые моменты, связанные с производительностью.
1) Каждый раз, когда вы получаете пользователяобъект, есть две поездки в базу данных вместо 1. Первая поездка для получения объекта;Вторая поездка для расшифровки SSN.Это может вызвать проблемы с производительностью, если вы не будете осторожны.
Рекомендация : НЕ расшифровывать автоматически зашифрованные поля!В моем примере, показанном выше, я расшифровал SSN, когда извлекал объект пользователя.Я сделал это только для демонстрационных целей!Спросите себя, действительно ли вам нужен SSN каждый раз, когда пользователь извлекается.Если возможно, выберите ленивое дешифрование вместо активного дешифрования!
2) Хотя я этого не демонстрировал, каждый раз, когда вы создаете / обновляете пользовательский объект, в базу данных также будут совершаться 2 поездки.Первая поездка для шифрования SSN;Вторая поездка для вставки объекта.Опять же, это может вызвать проблемы с производительностью, если вы не будете осторожны.
Рекомендация : учитывайте это снижение производительности, но не делегируйте шифрование и сохранение SSN как другой метод.Храните все это за одну операцию, иначе вы можете забыть сохранить все вместе.Таким образом, рекомендация по созданию / обновлению противоположна извлечению: выбирайте активное шифрование вместо ленивого шифрования!