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

ASP .NET Core disposing UnitOfWork before getting all data

我正在实施一个通用存储库 + 工作单元模式以及一个 WebApi 项目。我在获取一个实体并包含引用它的另一个实体的集合时遇到问题。

我首先通过代码映射了以下实体:

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

这是我的工作单位:

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

还有我的通用存储库:

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

控制器正在注入 RecipeService。在控制器中我有这个方法:

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

食谱服务注入 IUnitOfWork 并具有以下方法:

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

另外我注册的服务如下:

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

我的问题是当我得到一个指定的食谱(连同它的成分)时我得到一个 "The connection has been restarted" 错误(在 firefox 中)。在调试时,我可以看到我有配方及其成分。但是当返回 Ok(recipe) 并将结果映射到实体时,IUnitOfWork 在获得第一个成分后被处理。

谁能帮帮我?谢谢

问题是我有一个循环引用我没有得到任何异常。

我通过在 Startup class 的 ConfigureServices 方法中添加以下内容来修复:

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