【问题标题】:How to make a repository for class with <T> in EF如何在 EF 中使用 <T> 为类创建存储库
【发布时间】:2013-05-23 10:59:07
【问题描述】:

我有一个简单的课程:

public class TestClass<T> {
    public int ID { get; set; }
    public T Value { get; set; }
}

是否可以使用 EF Code First 和 Repository 模式将此类元素保存到 SQL 数据库?


编辑: 似乎无法使用 -notation 创建 DbSet。例如。

public class UnitOFWorkTestContext : DbContext {
    ...
    public DbSet<TestClass<int>> TestClass_Int { get; set; }
    ...
}

给出错误:

未映射类型“UnitOFWorkTest.Models.TestClass`1[System.Int32]”。使用 Ignore 方法或 NotMappedAttribute 数据注释检查该类型是否被显式排除。验证该类型是否被定义为一个类,不是原始的、嵌套的或泛型的,并且不是从 EntityObject 继承的。

【问题讨论】:

  • 在 Visual Studio 中通过右键单击“控制器”并选择“添加 -> 控制器”以及使用“脚手架控制器 TestClass”命令的包管理器控制台(我有“MVC脚手架”-安装包)
  • 那你得到了什么输出?
  • 从包管理器控制台:脚手架:找不到与名为“TestClass”的控制器相对应的模型类型。尝试提供 -ModelType 参数值。在 line:1 char:1 + Scaffold Controller TestClass + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo :未指定:(:) [Invoke-Scaffolder],RuntimeException + FullyQualifiedErrorId : T4Scaffolding.Cmdlets.InvokeScaffolderCmdlet
  • 感谢您的帮助!我只是在测试建议的解决方案...
  • 你只能传递类对象

标签: c# entity-framework ef-code-first repository-pattern


【解决方案1】:

下面是我自己的工作代码的副本。我不会假装我的代码是完美的,但它很方便并且具有松散的耦合性。此外,这将是相当大量的代码,但不要害怕 =)...

IEntity:

public interface IEntity
{
    int Id { get; set; }
}

AbstractRepository 和接口:

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);
        }
    }
}

具体存储库:

public class GroupRepository : AbstractRepository<Group, SurveyContext>
{
    public GroupRepository(UnitOfWork<SurveyContext> unit)
        : base(unit)
    {
    }
}

DbContext 继任者:

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; }
}

工作单元:

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()
    {
    }
}

用法:

using (var unit = new UnitOfWork<SurveyContext>())
{
    //ViewDataSynchronize.SynchronizeSectionsForGroup(context, model.SectionIds, model.Group);

    var repo = new GroupRepository(unit);
    repo.Add(model.Group);
    unit.Commit();
}

【讨论】:

  • 感谢您的出色回答!我尝试了您的示例并得到了解决方案。似乎无法使用 -notation 创建 DbSet。例如。 public class UnitOFWorkTestContext : DbContext { ... public DbSet&lt;TClass&lt;int&gt;&gt; TClass_Int { get; set; } ... 给出错误:未映射类型“UnitOFWorkTest.Models.TClass`1[System.Int32]”。使用 Ignore 方法或 NotMappedAttribute 数据注释检查该类型是否被显式排除。验证该类型被定义为一个类,不是原始的、嵌套的或泛型的,并且不是从 EntityObject 继承的。
  • 以下问题似乎可以解释您的情况:stackoverflow.com/questions/13000748/…
  • 您是否尝试使用普通的 .NET 类型而不是类?它不起作用。
  • @alex-g-p 我让您的解决方案使用简单的类,但不适用于带有 public class Test&lt;T&gt; {} 之类的签名的类似乎这些不属于类?
  • 是的,如果您将使用泛型类,这会有点困难,因为您应该在使用它的任何地方明确指定模板。
猜你喜欢
  • 2020-06-22
  • 2012-04-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-01
相关资源
最近更新 更多