简体   繁体   English

ASP.NET Core在获取所有数据之前先处理UnitOfWork

[英]ASP .NET Core disposing UnitOfWork before getting all data

I'm implementing a generic repository + Unit of work pattern along with a WebApi project. 我正在与WebApi项目一起实现通用存储库+工作单元模式。 I'm having problems with getting one entity and including the collection of another enttity that refers to it. 我在获取一个实体以及包含引用该实体的另一实体时遇到问题。

I have the following entities mapped through code first: 我首先通过代码映射了以下实体:

public class Ingredient : BaseEntity
{
    public string Name { get; set; }
    public string Amount { get; set; }
    public Guid RecipeId { get; set; }
    public virtual Recipe Recipe { get; set; }
}

public class Recipe : BaseEntity
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string ImagePath { get; set; }
    public virtual ICollection<Ingredient> Ingredients { get; set; }
}

This is my unit of work: 这是我的工作单元:

public class UnitOfWork<TContext> : IRepositoryFactory, IUnitOfWork<TContext>, IUnitOfWork where TContext : DbContext
{
    private readonly TContext context;
    private Dictionary<Type, object> repositories;

    public UnitOfWork(TContext context)
    {
        this.context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public TContext Context => context;

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : BaseEntity
    {
        if (repositories == null)
        {
            repositories = new Dictionary<Type, object>();
        }

        var type = typeof(TEntity);
        if (!repositories.ContainsKey(type))
        {
            repositories.Add(type, new Repository<TEntity>(context));
        }
        return (IRepository<TEntity>)repositories[type];
    }

    public int Commit()
    {
        return context.SaveChanges();
    }

    public void Dispose()
    {
        context?.Dispose();
    }
}

And my generic repository: 而我的通用存储库:

public class Repository<T> : IRepository<T> where T : BaseEntity
{
    protected readonly DbContext dbContext;
    protected readonly DbSet<T> dbSet;

    public Repository(DbContext context)
    {
        dbContext = context;
        dbSet = dbContext.Set<T>();
    }

    public T GetEntity(Guid id)
    {
        return dbSet.Find(id);
    }

    public T GetEntity(Guid id, params Expression<Func<T, object>>[] includeProperties)
    {
        IEnumerable<string> properties = GetProperties(includeProperties);

        IQueryable<T> queryable = dbSet;

        foreach (var property in includeProperties)
        {
            queryable = dbSet.Include(property);
        }

        return queryable.FirstOrDefault(x => x.Id == id);
    }

    [...]

    private static IEnumerable<string> GetProperties(Expression<Func<T, object>>[] includeProperties)
    {
        List<string> includelist = new List<string>();

        foreach (var item in includeProperties)
        {
            MemberExpression body = item.Body as MemberExpression;
            if (body == null)
                throw new ArgumentException("The body must be a member expression");

            includelist.Add(body.Member.Name);
        }
        return includelist.AsEnumerable();
    }
}

The controller is injecting the RecipeService. 控制器正在注入RecipeService。 In the controller I have this method: 在控制器中,我有这种方法:

    [HttpGet("{id}", Name = "Get")]
    public IActionResult Get(Guid id)
    {
        var recipe = recipeService.GetRecipe(id);
        if (recipe == null)
        {
            return NotFound();
        }
        return Ok(recipe);
    }

The recipe service injects the IUnitOfWork and has the following method: 配方服务将注入IUnitOfWork并具有以下方法:

    public Recipe GetRecipe(Guid id)
    {
        return repository.GetEntity(id, r => r.Ingredients);
    }

Also I have the services registered as follows: 我还注册了以下服务:

        services.AddScoped<IRepositoryFactory, UnitOfWork<TContext>>();
        services.AddScoped<IUnitOfWork, UnitOfWork<TContext>>();
        services.AddScoped<IUnitOfWork<TContext>, UnitOfWork<TContext>>();
        services.AddScoped<IRecipeService, RecipeService>();

My problem is when I'm getting a specified recipe(along with its ingredients) i got a "The connection has been restarted" error (in firefox). 我的问题是,当我得到指定的配方(及其配料)时,出现了“连接已重新启动”错误(在Firefox中)。 While debugging I can see that I have the recipe with its ingredients. 在调试时,我可以看到我有配方及其成分。 But when returning Ok(recipe) and mapping the result to the entities, the IUnitOfWork is disposed after getting the first ingredient. 但是,当返回Ok(recipe)并将结果映射到实体时,将在获取第一个成分后处置IUnitOfWork。

Anyone can help me out? 有人可以帮我吗? Thanks 谢谢

The problem was I was having a circular reference i wasn't getting any exception. 问题是我有一个循环引用,但没有任何异常。

I fixed by adding the following in the ConfigureServices method of the Startup class: 我通过在Startup类的ConfigureServices方法中添加以下内容来进行修复:

        services.AddMvc().AddJsonOptions(options =>
        {
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM