Questo approccio è scalabile?

0

Sto lavorando per riscrivere un'applicazione legacy (C ++) a C # ASP.NET MVC con EF6 ma ho intenzione di eseguire l'aggiornamento a ASP.NET Core1 e EF Core 1.

Lo schema del database è davvero arcano in quanto ha un singolo schema con tabelle con prefisso T_ * per se è transazionale e M_ * se è principale. Si supponga che l'oggetto Cliente sia rappresentato in DB come T_Customer e M_Customer con entrambe le tabelle con le stesse colonne. NOTA: il modello DB I non può essere modificato.

Ho generato codice prima dal database esistente e ora ho classi di entità per M_Customer e T_Customer. Tuttavia ritengo che il modello applicativo non debba essere vincolato o derivato dal modello DB.

Quindi sto cercando una classe astratta Customer che dovrebbe essere derivata da T_Customer e M_Customer e il mio livello di servizio controllerebbe il modo in cui questa classe Cliente dovrebbe essere salvata (a seconda di alcuni stati non mappati).

Il problema ora è che EF6 ed EF7 iniziano a lamentarsi che le mie classi di entità non possono avere chiavi duplicate (che non ho). Se mappo solo la classe T_Customer alla tabella T_Customer e class M_Customer alla tabella M_Customer, allora tutto va bene, ma non appena estendo questo approccio ad altre tabelle, EF inizia a lamentarsi delle chiavi primarie duplicate. Dopo molte ricerche non sono riuscito a trovare una soluzione che funzioni sia per EF6 sia per EFCore1.

Quindi ora penso che il mio DataContext possa convivere con le classi di entità T_Customer e M_Customer e li proietterò / mapperò alla classe Customer in livello di business logic / service.

Il mio progetto diventa quindi

  • Project.Entities - T_Customer, M_Customer, T_Entity e M_Entity classes
  • Project.Data - l'interfaccia IDataContext che ha fondamentalmente i metodi GetSingle, GetList, IUnitOfWork for Commit generici
  • Project.Data.EF6 - Classe derivata DbContext che implementa IDataContext, IUnitOfWork
  • Project.Data.EF7 - Classe derivata DbContext che implementa IDataContext, IUnitOfWork
  • Project.Core - Classi cliente / dominio e classi di servizio
  • Project.Presentation - Progetto ASP.NET MVC5, classi controller che funzionano con classi Cliente / Dominio

Riferimenti

  • Project.Entities è referenziato da Project.Data.EF6 e Project.Data.EF7
  • Project.Data è referenziato da Project.Core
  • Project.Core è referenziato da Project.Presentation

per es.

Project.Entities

public abstract class EntityBase {
}
public class T_Customer : EntityBase {
  public Guid Customer_PK {get;set;}
  public string CustomerName {get;set;}
  ...
  public virtual ICollection<T_Order> T_Orders {get;set;}
}
public class M_Customer : EntityBase {
  public Guid Customer_PK {get;set;}
  public string CustomerName {get;set;}
  ...
  public virtual ICollection<M_Order> M_Orders {get;set;}
}

public class M_Order : EntityBase {
  public Guid Order_PK{get;set;}
  ...
}
public class T_Order : EntityBase {
  public Guid Order_PK{get;set;}
}

Project.Data

public interface IDataReaderContext {
  IEnumerable<T> GetList<T>(Func<IQueryable<T>, IQueryable<T>> projection) where T : class;
  T GetSingle(Func<IQueryable<T>, IQueryable<T>> projection) where T : class;
}
public interfaace IUnitOfWork {
  int Commit();
}
public interface IDataContext : IDataReaderContext, IUnitOfWork {
  void Create<T>(T entity) where T : class;
  ...
}

Project.Data.EF6

public class ProjectDbContext : DbContext, IDataContext {
  ...
}

Project.Core.Domain

public abstract class DomainBase {
  public Guid Id {get;set;}
  ...
}
public class Customer {
  public string Name {get;set;}
  ...
  public ICollection<Order> Orders{get;set;}
}
public class Order {
  ...
}

le classi di dominio potrebbero avere un'autovalutazione

Project.Core.Services

public class CustomerService {
  private readonly Func<IDataContext> _contextFactory;
  public CustomerService(Func<IDataContext> contextFactory) {
    _contextFactory = contextFactory;
  }
  public Customer GetById(Guid id) {
    using(var context = _contextFactory.Invoke()) {
      var customer = context.GetSingle<M_Customer>(query => query.Where(c => c.Customer_PK == id));
      return customer.ProjectAs<Customer>();
    }
  }
}

ProjectAs è un metodo di estensione per le classi Entity che utilizza AutoMapper i metodi di servizio avranno validazione logica aziendale ecc.

Project.Presentation

public class CustomerController : Controller {
  private readonly ICustomerService _customerService;
  public CustomerController(ICustomerService customerService) {
    _customerService = customerService;
  }
  public ActionResult Details(Guid id) {
    return View(_customerService.GetById(id));
  }
}
I

metodi di controllo saranno sottili e convalidano solo l'input e invitano a chiamare i metodi di servizio

Sto facendo qualcosa di sbagliato? È scalabile? Intendo aggiungere uno strato di servizi Web WCF per terze parti da integrare con il nostro sistema. Non ho intenzione di modificare la mia presentazione per utilizzare il servizio web WCF invece di Project.Core.Services.

Potrei aver bisogno di supportare altre presentazioni / UI per diciamo Universal Windows Apps ecc.

    
posta user2321864 28.01.2016 - 15:16
fonte

0 risposte

Leggi altre domande sui tag