Лучшая практика в приложениях с несколькими базами данных Entity Framework
Я новичок в программировании на C# и ищу способ сделать несколько обобщений, чтобы лучше работать с Entity Framework, используя несколько баз данных.
Мое приложение было построено с использованием только Oracle Database, используя все сущности внутри моего приложения. Теперь у нас есть необходимость реализовать SQl Server и MySQL в этом приложении.
Для этого я сделал следующие шаги:
- Удалены все сущности из моего основного приложения;
- Создано 3 библиотеки классов, по одной для каждой базы данных, содержащей только модели и сгенерированные EF классы;
- Создана библиотека 4-го класса, содержащая общие классы, которые должны быть заполнены объектами каждой базы данных.
Эта "универсальная" библиотека классов содержит следующие элементы для каждой таблицы:
- Класс с одинаковым именем таблицы и одинаковыми полями (все базы данных имеют одинаковые имена таблиц и полей);
- Интерфейс, который реализует базовые методы;
- Абстрактный класс, который реализует методы интерфейса;
- Класс, который наследуется от моего абстрактного класса для каждой базы данных;
- Класс фабрики, который создает требуемый класс базы данных, используя перечисление типа базы данных.
Ниже я привожу пример, используя мою таблицу устройств:
namespace MyApp.Data
{
internal interface IDevicesDAO
{
IEnumerable<Device> GetDevices();
IEnumerable<Device> GetDevices(int serverId);
Device GetDeviceById(int deviceId);
}
public abstract class DeviceDAO: IDevicesDAO
{
public abstract IEnumerable<Business.Device> GetDevices();
public abstract IEnumerable<Business.Device> GetDevices(int serverId);
public abstract Business.Device GetDeviceById(int deviceId);
protected abstract IEnumerable<Business.Device> ListDevice(int code);
}
internal static class DeviceDAO_Factory
{
public static DeviceDAO Create(DatabaseTypeEnum databaseType)
{
switch (databaseType)
{
case DatabaseTypeEnum.Oracle:
return new DeviceDAO_Oracle();
default:
return null;
}
}
}
class DeviceDAO_Oracle: DeviceDAO
{
public override IEnumerable<Device> GetDevices()
{
return ListDevice(0);
}
public override IEnumerable<Device> GetDevices(int serverId)
{
return ListDevice(serverId);
}
public override Device GetDeviceById(int deviceId)
{
OracleContext db = new OracleContext();
try
{
DEVICE loaded = db.DEVICES.Where(d => d.DEVICEID == deviceId).FirstOrDefault();
if (loaded != null)
{
Device loaDevice = FillDevice(loaded);
return loaDevice;
}
else
{
return null;
}
}
finally
{
db.Dispose();
}
}
protected override IEnumerable<Device> ListDevice(int code)
{
OracleContext db = new OracleContext();
try
{
List<DEVICE> devicelList;
List<Device> resultList;
if (code == 0)
devicelList = db.DEVICES.Where(d => d.SERVERID == code).ToList();
else
devicelList = db.DEVICES.ToList();
if (devicelList != null)
{
resultList = new List<Device>();
foreach (DEVICE item in devicelList)
{
Device newDevice = FillDevice(item);
resultList.Add(newDevice);
}
return resultList;
}
else
{
return null;
}
}
finally
{
db.Dispose();
}
}
private Device FillDevice(DEVICE item)
{
Device current = new Device();
current.Serverid = item.SERVERID;
current.Deviceid = item.DEVICEID;
current.Description = item.DESCRIPTION;
current.Ipaddress = item.IPADDRESS;
current.Shots = item.SHOTS;
current.Matrixnumber = item.MATRIXNUMBER;
current.Shottime = item.SHOTTIME;
current.Imageresize = item.IMAGERESIZE;
current.Imagewidth = item.IMAGEWIDTH;
current.Imageheight = item.IMAGEHEIGHT;
current.Devicetype = item.DEVICETYPE;
current.Devicegroup = item.DEVICEGROUP;
current.Devicetag = item.DEVICETAG;
current.Frameinterval = item.FRAMEINTERVAL;
current.Delaytime = item.DELAYTIME;
current.Eventinput = item.EVENTINPUT;
current.Accesspointid = item.ACCESSPOINTID;
current.Username = item.USERNAME;
current.Password = item.PASSWORD;
current.Defaultencoder = item.DEFAULTENCODER;
current.Isactive = item.ISACTIVE;
current.Stream = item.STREAM;
current.Uriaddress = item.URIADDRESS;
current.Devicesectionid = item.DEVICESECTIONID;
current.Userid = item.USERID;
current.Lastupdate = item.LASTUPDATE;
current.Framerate = item.FRAMERATE;
current.Initializedevice = item.INITIALIZEDEVICE;
current.Serviceid = item.SERVICEID;
current.Insertdelay = item.INSERTDELAY;
current.Plateposition = item.PLATEPOSITION;
current.Biosid = item.BIOSID;
current.Lasttimeactive = item.LASTTIMEACTIVE;
current.Status = item.STATUS;
current.Selectedprofiletoken = item.SELECTEDPROFILETOKEN;
current.Detectionsensibility = item.DETECTIONSENSIBILITY;
current.OnvifPort = item.ONVIF_PORT;
current.Nvraddress = item.NVRADDRESS;
return current;
}
}
}
Мой вопрос:
Видите класс Oracle? Если я реализую SQL Server и MySQL, мне нужно будет создать еще 2 класса с одинаковым кодом, потому что существуют разные контексты и разные объекты таблиц (даже объекты, имеющие одинаковые имя и поле в разных контекстах).
Мне действительно не нравится эта практика, и я предполагаю, что это способ создания дженериков или коммьюнити баз для реализации всего этого более чистым способом.
Извините всех за длинный пост. Я старался быть максимально конкретным! Извините за плохой английский тоже:)
Любая помощь будет благодарна!
Спасибо!