0

我刚刚在这个问题上花了几个小时,我想在将来简化它,因为我可以看到它是一个常见的要求。

我有一个带有导航属性的 Question 类,它是一个集合:

public class AnsweredQuestion : ModelBase
{  
    public virtual ICollection<Answer> Answers { get; set; }  
}

我所有的模型都继承一个基类:

public abstract class ModelBase
{
    public int ID { get; set; }
}

现在我想从一组答案 id 中设置 Answers 集合,我的控制器中有这个方法 - 它确实有效

    private void SetAnswers(AnsweredQuestion question, 
                            IEnumerable<int> newAnswerIDs)
    {
        //First remove any answers we don't want
        question.Answers.RemoveAll(a => !newAnswerIDs.Contains(a.ID));

        //Then project the current ids
        IEnumerable<int> currentAnswerIds = question.Answers.Select(a => a.ID);

        //Now go to the database to get the answers that match the ids that 
        //we have to add
        IQueryable<Answer> answersToAdd = _uow.AnswerRepository.All                            
                 .Where(dbAnswers => newAnswerIDs.Contains(dbAnswers.ID) 
                                   &&
                                   !currentAnswerIds.Contains(dbAnswers.ID));

        //and add them to the navigation property  
        question.Answers.AddRange(answersToAdd);
    }

但是这段代码相当复杂,我可以看到我必须在每个有导航属性的模型中一次又一次地编写它。

如果这是一对多的关系,我的实体中会有一个 Answer 属性和一个 AnswerID 属性,框架将为我解决这个问题。但是,据我所知,我不能为多对多的关系做到这一点。

任何人都可以想办法把它变成可以在任何模型中的任何导航属性上调用的方法吗?我想过在模型集合上创建一个扩展方法,但我的绊脚石是我需要去数据库获取与我的 id 匹配的 Answers,然后再将它们添加到 Answers 集合中,这意味着我的扩展方法需要知道要使用哪个存储库

4

1 回答 1

0

这是我想出的:

public static bool SetById<T>(this ICollection<T> collection,
    IEnumerable<int> ids,
    IRepository<T> repo)
where T : ModelBase
{
    //First remove any answers we don't want
    int count = collection.Count;
    collection.RemoveAll(a => !ids.Contains(a.ID));
    bool isAltered = count != collection.Count;

    //Then project the current ids
    IEnumerable<int> currentIds = collection.Select(a => a.ID);

    IQueryable<T> toAdd = repo.All.Where(dbAnswers => ids.Contains(dbAnswers.ID) && !currentIds.Contains(dbAnswers.ID));
    isAltered = isAltered || toAdd.Any();

    //and add them to the navigation property
    collection.AddRange(toAdd);

    return isAltered;
}

这取决于我的所有实体都继承自具有 ID 的基类:

public abstract class ModelBase
{
    public int ID { get; set; }
}

在我的控制器中,我这样称呼它(传入我的存储库):

    question.Answers.SetById(newAnswerIDs, _uow.AnswerRepository);
于 2013-06-17T10:09:20.520 回答