如何在C#中的通用规范模式中为嵌套对象添加.ThenInclude

问题描述

我已经为通用仓库实现了通用规范模式,但是我不知道如何在代码添加.ThenInclude()
仅供参考-我有3个实体(User->PracticedStyles->YogaStyles),当我去获取我的User时,我想获取他/她实践的所有YogaStyles(例如bikram,vinyasa等)。但是我无法获取YogaStyle实体,我可以获取PracticedStyle的所有User实体,因为它只是一个实体,但我不知道如何获取/包括每个YogaStyle中的PracticedStyle实体。

我正在使用带有通用存储库模式的通用规范模式,并且已经创建了一个包含所有样式的中间表,也许这是错误的,或者我不知道如何正确使用通用规范模式? / p>

public class User : IdentityUser<int>
{
   public ICollection<PracticedStyle> PracticedStyles { get; set; }
}
public class PracticedStyle : BaseEntity
{
    public int UserId { get; set; }
    public User User { get; set; }
    public int YogaStyleId { get; set; }
    public YogaStyle YogaStyle { get; set; }
}
public class YogaStyle : BaseEntity
{
    public string Name { get; set; } // strength,vinyasa,bikram,etc
}

这是我的控制器以及该控制器从中调用方法

[HttpGet("{id}",Name = "GetMember")]
public async Task<IActionResult> GetMember(int id)
{
   var spec = new MembersWithTypesspecification(id);
   var user = await _membersRepo.GetEntityWithSpec(spec);
   if (user == null) return NotFound(new ApiResponse(404));
   var userToReturn = _mapper.Map<MemberForDetailDto>(user);
   return Ok(userToReturn);
}
public class MembersWithTypesspecification : BaseSpecification<User>
{
   public MembersWithTypesspecification(int id) 
        : base(x => x.Id == id) 
    {
        AddInclude(x => x.UserPhotos);
        AddInclude(x => x.Experience);
        AddInclude(x => x.Membership);
        AddInclude(x => x.PracticedStyles);
        // doesn't work - yogastyles is not a collection
        // AddInclude(x => x.PracticedStyles.YogaStyles);
        AddInclude(x => x.InstructedStyles);
    }
}

这是BaseSpecification中的“ AddInclude”

public class BaseSpecification<T> : ISpecification<T>
{
   public BaseSpecification()
    {
    }

    public BaseSpecification(Expression<Func<T,bool>> criteria)
    {
        Criteria = criteria;
    }
   public List<Expression<Func<T,object>>> Includes { get; } = new List<Expression<Func<T,object>>>();
   protected void AddInclude(Expression<Func<T,object>> includeExpression)
    {
        Includes.Add(includeExpression);
    }
}

这是getEntityWithSpec

public async Task<T> GetEntityWithSpec(ISpecification<T> spec)
{
   return await ApplySpecification(spec).FirstOrDefaultAsync();
}
private IQueryable<T> ApplySpecification(ISpecification<T> spec)
{
    return SpecificationEvaluator<T>.GetQuery(_context.Set<T>().AsQueryable(),spec);
}

和规格评估者

public class SpecificationEvaluator<TEntity> where TEntity : class // BaseEntity // when using BaseEntity,we constrain it to on base entities
{
    public static IQueryable<TEntity> GetQuery(IQueryable<TEntity> inputQuery,ISpecification<TEntity> spec)
    {
        var query = inputQuery;

        if (spec.Criteria != null)
        {
            query = query.Where(spec.Criteria); // e => e.YogaEventTypeId == id
        }

        if (spec.OrderBy != null)
        {
            query = query.OrderBy(spec.OrderBy);
        }

        if (spec.OrderByDescending != null)
        {
            query = query.OrderByDescending(spec.OrderByDescending);
        }

        if (spec.IsPagingEnabled)
        {
            query = query.Skip(spec.Skip).Take(spec.Take);
        }

        query = spec.Includes.Aggregate(query,(current,include) => current.Include(include)); // 'current' represents entity

        return query;
    }
}

解决方法

这是一个解决方案。让您的AddInclude方法返回类似ISpecificationInclude的内容:

public interface ISpecificationInclude<TFrom,TTo>
    where TFrom : IEntity
    where TTo : IEntity
// I know that you do not have a `IEntity` interface,but I advise you to
// add it to your infrastructure and implement it by all your entity classes.
{
    ISpecificationInclude<TTo,TAnother> ThenInclude<TAnother>(Expression<Func<TTo,TAnother>> includeExpression);
    ISpecificationInclude<TTo,IEnumerable<TAnother>>> collectionIncludeExpression);
}

适当地实现此接口。该实现应该是单个“ include”表达式的包装。您可能需要两种实现:一种用于包装集合包含,另一种用于简单对象包含。

Includes类的BaseSpecification属性应该是此接口的集合。

在您的SpecificationEvaluator中,递归处理您的Includes及其所有ThenIncludes

我知道有很多代码,但是恐怕别无他法了:)

,

我知道了我需要什么。 遵循此link 我需要添加

AddInclude($"{nameof(User.PracticedStyles)}.{nameof(PracticedStyle.YogaStyle)}");

query = specification.IncludeStrings.Aggregate(query,(current,include) => current.Include(include));

public List<string> IncludeStrings { get; } = new List<string>();
protected virtual void AddInclude(string includeString)
{
    IncludeStrings.Add(includeString);
}

这使我可以使用.thenInclude(),但可以用作一系列字符串。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...