I'd like to insert my UserCompany
object into the database trought a single method. Such as passing the element to this function, take it and "insert in the right table".
Usually in Entity (such as LINQ to XML) I do somethings like:
db.Company.UsersCompany.Add(UserCompany);
db.SubmitChanges();
but the problem here is that I need to specify the table UsersCompany
and Company
before using the .Add()
.
I'd like (since I want to do ONE function for the insert for each type of object/table) get rid of this. Such as having a:
UserCompany.InsertMySelf();
or
db.SmartAdd(UserCompany);
and it know how to insert the table, where and how, automatically.
Is it possible to do this? Is there any strategies?
You can solve this with generics:
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
Sorry for using VB...
In C#:
public void AddEntities<TEntity>(IEnumerable<TEntity> entities)
{
foreach(ent in entities)
{
_db.Set<TEntity>.Add(ent);
}
_db.SaveChanges();
}
In your Controller
define a repository for yourself along these lines:
public class CompanyController : ApiController
{
private readonly CompanyRepository _companyRepository;
public CompanyController()
{
_companyRepository= new CompanyRepository(User);
}
[HttpPost]
public Company PostCompany(Company comp)
{
_companyRepository.SmartAdd(comp);
}
}
Define a repository with the definition:
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;
}
}
There will have to be some adaption to suite your own needs, but this is the general idea.
Although there could potentially be a lot of cases within the switch, I assume you will do object validation and other things regardless, so you can easily do that here too.
Relevant links:
- Unit Of Work
Pattern
- Repository
Pattern
You need to look at the generic repository. This pattern feeds all the CRUD through one base class. You can then inherit from this class to implement custom repositories where it's necessary
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; }
}
References:
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