问题
I have a simple class:
public class TestClass<T> {
public int ID { get; set; }
public T Value { get; set; }
}
Is is possible to use EF Code First and Repository pattern to save this kind of elements to SQL database?
Edit: It seems like the DbSet's cannot be created using the -notation. E.g.
public class UnitOFWorkTestContext : DbContext {
...
public DbSet<TestClass<int>> TestClass_Int { get; set; }
...
}
Gives error:
The type 'UnitOFWorkTest.Models.TestClass`1[System.Int32]' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive, nested or generic, and does not inherit from EntityObject.
回答1:
Below is the copy of my own working code. I do not pretending that my code is perfect, but it is handy and has loose coupleness. Also, it will be quite big amount of code, but do not be afraid =)...
IEntity:
public interface IEntity
{
int Id { get; set; }
}
AbstractRepository and interface:
public interface IRepository<T>
{
IEnumerable<T> List();
IEnumerable<T> List(Func<T, bool> pred);
T Get(int id);
T Get(Func<T, bool> pred);
void Add(T entity);
T Update(T entity);
void Delete(T entity);
void Delete(Func<T, bool> pred);
}
public abstract class AbstractRepository<TEntity, TContext> : IRepository<TEntity>
where TContext : DbContext, new()
where TEntity : class, IEntity
{
protected TContext context;
public AbstractRepository(UnitOfWork<TContext> unit)
{
context = unit.Context;
}
public virtual IEnumerable<TEntity> List()
{
return context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> List(Func<TEntity, bool> pred)
{
return context.Set<TEntity>().Where(pred);
}
public virtual TEntity Get(int id)
{
return context.Set<TEntity>().Find(id);
}
public virtual TEntity Get(Func<TEntity, bool> pred)
{
return context.Set<TEntity>().FirstOrDefault(pred);
}
public virtual void Add(TEntity entity)
{
if (entity.Id <= 0)
context.Entry(entity).State = System.Data.EntityState.Added;
}
public virtual TEntity Update(TEntity entity)
{
if (entity.Id > 0)
{
context.Entry(entity).State = System.Data.EntityState.Modified;
return entity;
}
return null;
}
public virtual void Delete(TEntity entity)
{
context.Entry(entity).State = System.Data.EntityState.Deleted;
}
public virtual void Delete(Func<TEntity, bool> pred)
{
foreach (var entity in List(pred))
{
Delete(entity);
}
}
}
Concrete repository:
public class GroupRepository : AbstractRepository<Group, SurveyContext>
{
public GroupRepository(UnitOfWork<SurveyContext> unit)
: base(unit)
{
}
}
DbContext successor:
public class SurveyContext: DbContext
{
public SurveyContext() : base("name=ApplicationConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Optional
modelBuilder.Configurations.Add(new Confuration1());
modelBuilder.Configurations.Add(new Confuration2());
modelBuilder.Configurations.Add(new Confuration3());
modelBuilder.Configurations.Add(new GroupConfiguration());
base.OnModelCreating(modelBuilder);
}
public DbSet<Group> Groups { get; set; }
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
}
Unit of work:
public class UnitOfWork<TContext> : IDisposable
where TContext: DbContext, new()
{
public TContext Context { get; private set; }
public UnitOfWork(TContext context)
{
Context = context;
}
public UnitOfWork() : this(new TContext())
{
}
public void Commit()
{
Context.SaveChanges();
}
public void Dispose()
{
}
}
Usage:
using (var unit = new UnitOfWork<SurveyContext>())
{
//ViewDataSynchronize.SynchronizeSectionsForGroup(context, model.SectionIds, model.Group);
var repo = new GroupRepository(unit);
repo.Add(model.Group);
unit.Commit();
}
回答2:
I think this link may be helpful for u
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
来源:https://stackoverflow.com/questions/16712177/how-to-make-a-repository-for-class-with-t-in-ef