Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
238 views
in Technique[技术] by (71.8m points)

c# - Class Mapping Error in repository pattern

I'm trying to implement the repository pattern on top of EF Core 5.

I have the repository and its interface defined this way:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, new()
{
    protected readonly DbContext DbContext ;

    public Repository(DbContext dbContext)
    {
        DbContext = dbContext;
    }

    public IQueryable<TEntity> GetAll()
    {
        try
        {
            return DbContext .Set<TEntity>();
        }
        catch (Exception ex)
        {
            throw new Exception($"Couldn't retrieve entities: {ex.Message}");
        }
    }
    ....
}

public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
}

Now I'm trying to create a DataManager in order to instantiate the repository using injection and query the database like the following:

public class BaseController : ControllerBase
{
   protected readonly DataManager dataManager;

    [HttpGet]
    public async Task<ActionResult> DoSomething()
    {
         Repository<MyEntity> entities= dataManager.GetRepository<MyEntity>();
         return Ok(entities.GetAll().Where(w=>w.EntityId>123));
    }
}

I've tried to implement the DataManager like the following:


public class DataManager : IDisposable 
{

    // keep one EFCore context per instance
    private DbContext ctx;


    public DataManager()
    {
        // create instance of context when DataManager is created
        ctx = new DbContext();
    }


    /// <summary>
    /// Dispose context if DataManager is disposed
    /// </summary>
    public void Dispose()
    {
        ctx.Dispose();
    }

    public Repository<TEntity> GetRepository<TEntity>()
    where TEntity : class
    {
        Repository<TEntity> service = null;

        var RepoName = "AuthenticationServer.Models.Repositories." + typeof(TEntity).Name + "Repository";
        try
        {
            var type = Type.GetType(RepoName);
            service = (Repository<TEntity>)Activator.CreateInstance(type, ctx);
        }
        catch (Exception e)
        {
            //default generic repo
            service = new Repository<TEntity>(ctx);
        }
        return service;
    }

}

But I get the following error on public Repository GetRepository() and TEntity in general:

TEntity must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TEntity' in the generic type or method Repository

How can I solve it? I think I've missed something in the repository pattern

question from:https://stackoverflow.com/questions/65945061/class-mapping-error-in-repository-pattern

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's your type constraints on Repository<TEntity>

Repository<TEntity> : IRepository<TEntity> where TEntity : class, new()

Which should match the type constraints on GetRepository, but doesn't.

public Repository<TEntity> GetRepository<TEntity>()
where TEntity : class

Try this:

public Repository<TEntity> GetRepository<TEntity>()
where TEntity : class, new()

Your code thinks you can call GetRepository with a type that doesn't have a parameterless constructor. But Repository itself insists it must.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...