2013-10-03 6 views
2

Я хотел бы вставить мой объект UserCompany в базу данных, вызванную одним методом. Например, передав элемент этой функции, возьмите его и «вставьте в правую таблицу».Автоматическая/Интеллектуальная вставка объекта «сам»

Обычно в Entity (например, LINQ к XML) Я делаю нечто вроде:

db.Company.UsersCompany.Add(UserCompany); 
db.SubmitChanges(); 

, но проблема в том, что мне нужно указать таблицу UsersCompany и Company перед использованием .Add(). Я бы хотел (так как я хочу сделать ONE функцию для вставки для каждого типа объекта/таблицы) избавиться от этого. Такие, как имеющие:

UserCompany.InsertMySelf(); 

или

db.SmartAdd(UserCompany); 

и знать, как вставить таблицу, где и как, автоматически.

Возможно ли это? Есть ли какие-либо стратегии?

+1

Образцовый шаблон поверх вашего контекста? Переключатель на основе типа объекта внутри этого метода? –

+0

Можете ли вы привести мне пример? – markzzz

+1

yep, дайте мне несколько минут, чтобы ввести код. –

ответ

1

В вашем Controller определить хранилище для себя вдоль этих линий:

public class CompanyController : ApiController 
{ 
    private readonly CompanyRepository _companyRepository; 

    public CompanyController() 
    { 
     _companyRepository= new CompanyRepository(User); 
    } 

    [HttpPost] 
    public Company PostCompany(Company comp) 
    { 
     _companyRepository.SmartAdd(comp); 
    } 
} 

Определение хранилища с определением:

public class CompanyRepository : EFContextProvider<CompanyContext> 
{ 
    // Fields which can be used for security within the repository. 
    public IPrincipal User { get; private set; } 
    public string UserName { get; set; } 

    public CompanyRepository (IPrincipal user) 
    { 
     User = user; 
     UserName = user.Identity.Name; 
    } 

    public DbQuery<Object> SmartAdd(Object obj) 
    { 
     switch (obj.GetType) 
     { 
      case "": // TODO... 
       Context.Company.UsersCompany.Add(UserCompany); 
       break; 

      default: 
       break; 
     } 
    } 

Там должен быть некоторыми адаптациями номера своих собственных потребностей, но это общая идея.

Хотя в коммутаторе может быть много случаев, я предполагаю, что вы будете выполнять проверку объекта и другие вещи независимо от того, что вы тоже можете сделать здесь.

Соответствующие ссылки:

+0

Это то, чего я бы хотел избежать: «выбрать случай». Что, если у меня есть 25 таблиц? Выключатель с 25 корпусом? Uhm ... непоследовательно ... – markzzz

+0

Как это непоследовательно? Это все в одном месте, и это, безусловно, более управляемо для людей, работающих с фактическим API. Вы можете разбить его еще больше и продолжать абстрагировать его, если хотите, но я не думаю, что это поможет вашему делу. В противном случае определите тип для каждого объекта в вашей базе данных, а затем запустите SQL для каждой схемы таблицы на основе объекта, который вы пытаетесь сохранить, чтобы просто потерять производительность и пространство. –

2

Вы можете решить эту проблему с обобщениями:

Public Sub AddEntities(Of TEntity)(entities As IEnumerable(Of TEntity)) 
    For Each ent In entities 
     _db.Set(Of TEntity).Add(ent) 
    Next 
    _db.SaveChanges() 
End Sub 

К сожалению для использования VB ... В C#:

public void AddEntities<TEntity>(IEnumerable<TEntity> entities) 
    { 
    foreach(ent in entities) 
    { 
     _db.Set<TEntity>.Add(ent); 
    } 
    _db.SaveChanges(); 
    } 
0

Вам необходимо посмотреть общий репозиторий. Этот шаблон передает все CRUD через один базовый класс.Вы можете наследовать от этого класса для реализации пользовательских хранилищ, где это необходимо

public class RepositoryBase<T> : IRepository<T> where T : ModelBase 
{ 
    private readonly IUnitOfWork _UnitOfWork; 
    //https://stackoverflow.com/questions/4442828/entity-framework-4-ctp-4-ctp-5-generic-repository-pattern-and-unit-testable/4458250#4458250 


    protected MyContext Context { get { return _UnitOfWork.Context; } } 

    public RepositoryBase(IUnitOfWork unitOfWork) 
    { 
     _UnitOfWork = unitOfWork; 
    } 

    public virtual T InsertOrUpdate(T e) 
    { 
     DbSet<T> dbSet = Context.Set<T>(); 

     DbEntityEntry<T> entry; 
     if (e.GetType().BaseType != null && e.GetType().Namespace == "System.Data.Entity.DynamicProxies") 
     { 
      //The entity being added is already a proxy type that supports lazy loading 
      //just get the context entry 
      entry = Context.Entry(e); 
     } 
     else 
     { 
      //The entity being added has been created using the "new" operator. 
      //Generate a proxy type to support lazy loading and attach it 
      T instance = dbSet.Create(); 
      instance.ID = e.ID; 
      entry = Context.Entry(instance); 
      dbSet.Attach(instance); 

      //and set it's values to those of the entity 
      entry.CurrentValues.SetValues(e); 
      e = instance; 
     } 

     entry.State = e.ID == default(int) ? 
           EntityState.Added : 
           EntityState.Modified; 

     return e; 
    } 

    public virtual IQueryable<T> All 
    { 
     get 
     { 
      return Context.Set<T>(); 
     } 
    } 

    public virtual IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties) 
    { 
     IQueryable<T> query = All; 
     foreach (var includeProperty in includeProperties) 
     { 
      query = query.Include(includeProperty); 
     } 
     return query; 
    } 

    public virtual T Find(int id) 
    { 
     T e = Context.Set<T>().Find(id); 
     if (e == null) 
      return null; 

     return e; 
    } 

    public virtual void Delete(int id) 
    { 
     var e = Context.Set<T>().Find(id); 

     if (e != null) 
      Context.Set<T>().Remove(e); 

    } 
} 

public abstract class ModelBase 
{ 
    public int ID { get; set; } 
} 

Ссылки:

The repository and unit of work patterns

John Papa's original source

How to ensure proxies are created when using the repository pattern

Generic Repository Pattern

Смежные вопросы