Использование DI с Entity Framework и несколькими контекстами данных в ASP.NET MVC - PullRequest
0 голосов
/ 17 апреля 2019

Мне интересно, как мы можем справиться с ситуацией, и если я поступаю об этом неправильно.Мы написали веб-приложение на основе одной модели схемы базы данных ERP.Мы используем Entity Framework для системы с методом внедрения регулярных зависимостей.

Теперь, когда мы приобрели несколько ERP в других лабораториях, мы пытаемся разрешить использование их данных на нашем первом оригинальном веб-портале, созданном для нашей оригинальной ERP.Как вы можете себе представить, это грубо, поскольку модели и дизайн баз данных не будут совпадать с нашими.Например, что-то вроде GetAllAssets() хранимой процедуры возвращает сложный тип, а затем привязывается к уровню репо, уровню обслуживания и представлению.

Я думал о том, что мы можем добавить несколько EDMX (контекст для баз данных), а затем сохранить все, начиная от представлений и заканчивая контроллерами и уровнем обслуживания.На уровне сервиса и введите params для наших классов, и мы могли бы передать контекст, в который вошел текущий пользователь, а затем в auto mapper добавить новые записи для новых вызовов контекста базы данных из Entity Framework, чтобы отобразить наш оригинальный кодот сервиса обратно к представлению.

Возможно ли это, или это хорошая или плохая идея?

Вот пример текущего базового контроллера, который мы используем в стиле DI,и я удалил много кода для примера этого вопроса:

[AuthorizeWithSession]
public class LocationController : Controller
{
    private readonly IMProAssetLocationService _mProAssetLocationService;
    private readonly IUIDataService _uiDataService;

    public LocationController(IMProAssetLocationService mProAssetLocationService,
        IUIDataService uiDataService)
    {
        _mProAssetLocationService = mProAssetLocationService;
    }

    public ActionResult List()
    {
        return View();
    }

    public ActionResult List2()
    {
        return View();
    }

    public ActionResult GetLocationList([DataSourceRequest]DataSourceRequest request)
    {
        //var result = DepartmentService.GetDepartmentList(SessionHelper.GetCustId());
        var result = _mProAssetLocationService.MProAssetLocationGetLocationByCustID(SessionHelper.GetCustId(), null);

        if (result != null && result.Any())
        {
            return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        }
    }
}

Уровень обслуживания интерфейса:

public interface IMProAssetLocationService
{
    IEnumerable<LocationVm> MProAssetLocationGetLocationByCustID(string custId,string id);
    string MProAssetLocationInsertLocation(LocationVm vm);
    void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
    void MProAssetLocationUpdateLocationByCustIDAndLocationID(LocationVm vm);
}

Уровень обслуживания:

public class MProAssetLocationService : LogManager, IMProAssetLocationService
{
    private readonly IMProAssetLocationRepo _mProAssetLocationRepo;

    public MProAssetLocationService(IMProAssetLocationRepo mProAssetLocationRepo)
    {
        _mProAssetLocationRepo = mProAssetLocationRepo;
    }

    protected override Type LogPrefix
    {
        get { return this.GetType(); }
    }

    public IEnumerable<LocationVm> MProAssetLocationGetLocationByCustID(string custId, string id)
    {
        List<LocationVm> listlocationVm = new List<LocationVm>();

        try
        {
            var records = _mProAssetLocationRepo.MProAssetLocationGetLocationByCustID(custId,id);
         }
   }

Слой репозитория интерфейса:

public interface IMProAssetLocationRepo : IRepository<MProAssetLocation>
{
    IEnumerable<string> GetMProAssetLocatonByCustId(string custId);
    IEnumerable<string> GetMProAssetLocatonDescriptionByCustId(string custId);
    IEnumerable<LocationView> GetMProAssetLocatonListByCustId(string search, string locationID, string custId);
    IEnumerable<LocationView> MProAssetLocationGetLocationByCustID(string custId, string id);
    string MProAssetLocationInsertLocation(LocationView lv);
    void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);

    void MProAssetLocationUpdateLocationByCustIDAndLoacationID(LocationView lv);
}

Слой репо:

public class CalLocationsRepo : RepositoryBase<CalLocaton>, ICalLocationsRepo
{
    public CalLocationsRepo(IDbFactory dbFactory)
        : base(dbFactory)
    {
    }

    //WHERE CalCodeActive=1 AND CalCodeGroup='OSS' ORDER BY CalCode
    public IEnumerable<string> GetCalLocations(string empID)
    {
        return DbContext.TAM_GetCalLocationsList(empID).ToList();
    }
}

Я думал о чем-то вроде использования типа контекста в нашей системе.Я знаю, что вызовы моделей сущностей будут называться по-разному в зависимости от наших различных баз данных, использующих свои собственные хранимые процедуры, но, подумав на уровне, предшествующем вызову, я проверяю контекст для использования, а затем выполняю соответствующий вызов следующим образом:

public class DBContextRepo<T> : RepositoryBase, IDBContextRepo<T>
{
    DBContextRepo<T> _typeParameterClass;

    public DBContextRepo(IDbFactory dbFactory, DBContextRepo<T> typeParameterClass)
      : base(dbFactory)
    {
        _typeParameterClass = typeParameterClass;
    }

    public List<string> GetAllModelsByManufcaturer(string manufacturerName)
    {
        List<string> results = new List<string>();

        if (_typeParameterClass.GetType() == typeof(TAM.DataLayer.EntityModels.QuoteWerks1Entities))
        {
            using(var dbContext = DbContextQw)
            {
                var items = dbContext.Products_OurProducts_Products.Where(p => p.Manufacturer == manufacturerName).ToList();

                results = items.Select(p => p.ManufacturerPartNumber).ToList();
            }
        }
        else
        {
            using (var dbContext = DbContext)
            {
                var items = dbContext.Models.Where(a => a.Manufacturer.MfrName == manufacturerName);
                results = items.Select(m => m.ModelNumber).ToList();
            }
        }

        return results;
    }
}

Это вызывает ошибки и я не уверен, как обработать два DBContext:

 public class DbFactory : Disposable, IDbFactory
{
    private TAMModel _dbContext;
    private QuoteWerks1Entities _dbContextQW;

    public TAMModel Init()
    {
        return _dbContext ?? (_dbContext = new TAMModel());
    }

    public QuoteWerks1Entities InitQW()
    {
        return _dbContextQW ?? (_dbContextQW = new QuoteWerks1Entities());
    }
    protected override void DisposeCore()
    {
        if (_dbContext != null)
        {
            _dbContext.Dispose();
        }

        if (_dbContextQW != null)
        {
            _dbContextQW.Dispose();
        }
    }
}

После того, как я добавил второй контекст, весь мой обычный код говорит, что в конструкторах нет соответствующего типанапример, такой:

 public class ContractRepo : RepositoryBase<Contract>, IContractRepo
{
    public ContractRepo(IDbFactory dbFactory)
        : base(dbFactory)
    {
    }


    public string GetContractIdentifyByCustId(string custId)
    {
        return DbContext.TAM_GetContractIdentifyByCustId(custId).SingleOrDefault();
    }

}

Вот класс BaseRepo:

  public class RepositoryBase
{
    private readonly TAMModel _dataContext;
    private readonly QuoteWerks1Entities _dataContextQW;
    protected IDbFactory DbFactory { get; private set; }

    protected TAMModel DbContext
    {
        get
        {
            return _dataContext ?? DbFactory.Init();
        }
    }

    protected QuoteWerks1Entities DbContextQw
    {
        get
        {
            return _dataContextQW ?? DbFactory.InitQW();
        }
    }

    protected RepositoryBase(IDbFactory dbFactory)
    {
        DbFactory = dbFactory;
    }

}

public abstract class RepositoryBase<T> where T : class
{
    private readonly TAMModel _dataContext;
    private readonly IDbSet<T> _dbSet;
    private readonly IDbSet<T> _dbSetQW;
    private readonly QuoteWerks1Entities _dataContextQW;

    protected IDbFactory DbFactory { get; private set; }

    protected TAMModel DbContext
    {
        get
        {
            return _dataContext ?? DbFactory.Init();
        }
    }

    protected QuoteWerks1Entities DbContextQW
    {
        get
        {
            return _dataContextQW ?? DbFactory.InitQW();
        }
    }

    protected RepositoryBase(IDbFactory dbFactory, T type)
    {
        DbFactory = dbFactory;
        _dbSet = DbContext.Set<T>();

        _dbSetQW = DbContextQW.Set<T>();
    }

    public virtual void Add(T entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Update(T entity)
    {
        _dbSet.Attach(entity);
        DbContext.Entry(entity).State = EntityState.Modified;
    }

    public virtual void Delete(T entity)
    {
        _dbSet.Remove(entity);
    }

    public virtual void Delete(Expression<Func<T, bool>> where)
    {
        IEnumerable<T> objects = _dbSet.Where<T>(where);
        foreach (T obj in objects)
        {
            _dbSet.Remove(obj);
        }
    }

    public virtual T GetById(int id)
    {
        return _dbSet.Find(id);
    }

    public virtual T GetById(string id)
    {
        return _dbSet.Find(id);
    }

    public virtual IEnumerable<T> GetAll()
    {
        return _dbSet.ToList();
    }

    public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
    {
        return _dbSet.Where(where).ToList();
    }

    public T Get(Expression<Func<T, bool>> where)
    {
        return _dbSet.Where(where).SingleOrDefault();
    }

    public virtual IQueryable<T> Query()
    {
        return _dbSet;
    }

    public virtual IQueryable<T> Query(Expression<Func<T, bool>> where)
    {
        return _dbSet.Where(where);
    }

    public virtual ObjectQuery<U> CreateQuery<U>(string query, ObjectParameter[] parameters)
    {
        return CastAsObjectContext().CreateQuery<U>(query, parameters);
    }

    public virtual ObjectQuery<U> CreateQuery<U>(string query)
    {
        return CreateQuery<U>(query, new ObjectParameter[0] { });
    }

    public virtual ObjectQuery<DbDataRecord> CreateQuery(string query, ObjectParameter[] parameters)
    {
        return CreateQuery<DbDataRecord>(query, parameters);
    }

    public virtual ObjectQuery<DbDataRecord> CreateQuery(string query)
    {
        return CreateQuery<DbDataRecord>(query);
    }

    private ObjectContext CastAsObjectContext()
    {
        var oContext = (DbContext as IObjectContextAdapter).ObjectContext;

        return oContext;
    }

}

Единственная проблема заключается в том, как установить контекст для входа в систему при использовании внедрения зависимостей?Будет ли это работать, так как в данный момент я все еще нахожусь в процессе, или я слишком усложняю это и поступаю неправильно?Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...