Сначала добавьте отношение ко многим ко многим в коде структуры объекта - PullRequest
0 голосов
/ 22 ноября 2011

Я хочу добавить связь между несколькими существующими сущностями и другой существующей сущностью. Вот моя модель:

public class Term
{
    public int TermId { get; set; }
    public virtual ICollection<SubForm> SubForms { get; set; }
}

public class SubForm
{
    public int SubFormId { get; set; }
    public virtual ICollection<Term> Terms { get; set; }
}

У меня есть метод обновления хранилища следующим образом:

public IQueryable<Term> GetTerms()
{
    IQueryable<Term> query = db.Terms.AsNoTracking();
    return query;
}

public Term UpdateTerm(Term term, IEnumerable<Expression<Func<Term, object>>> properties)
{
    if (term.TermId == 0)
    {
        throw new InvalidOperationException("Term does not exist");
    }
    db.Terms.Attach(term);
    if (properties != null)
    {
        foreach (var selector in properties)
        {
            string propertyName = Helpers.PropertyToString(selector.Body);
            db.Entry(term).Property(propertyName).IsModified = true;
        }
    }
    db.SaveChanges();
    return term;
}

Теперь я предполагаю, что это будет работать, когда я сделаю этот вызов в моем слое обслуживания:

public void AddFormToTerm(int termId, int formId)
{
    var term = termsRepository.GetTerms().FirstOrDefault(t => t.TermId == termId);
    var subForms = termsRepository.GetSubForms().Where(t => t.FormId == formId);

    //I assume this would work by adding existing forms to an existing term.
    foreach (var subForm in subForms)
    {
        term.SubForms.Add(subForm);
    }

    termsRepository.UpdateTerm(term, null);
}

К сожалению, это не обновляется, в промежуточной таблице ничего не было, когда я проверял базу данных. Также не было исключений.

1 Ответ

1 голос
/ 22 ноября 2011

Использование AsNoTracking в этом случае является проблемой.Без AsNoTracking это будет работать.Вы должны помнить, что вы можете обновлять отношения «многие ко многим» только с помощью механизма отслеживания изменений.Но в вашем коде EF-контекст узнает о term и коллекции SubForms впервые, когда вы вызовете Attach в своем методе UpdateTerm.EF не замечает, что вы добавили SubForms к term, потому что эти объекты не были присоединены к контексту (поскольку вы использовали AsNoTracking = "EF, пожалуйста, не присоединяйте к контексту!").Но после Attach ничего не произошло, прежде чем вы позвонили SaveChanges = Без изменений = Нет команд базы данных.Поэтому удаление AsNoTracking (или создание другого метода или параметра для загрузки с отслеживанием ) - лучший вариант.Все остальное будет связано с такими уродливыми «хитростями», как этот:

public Term UpdateTerm(Term term, ...)
{
    //...

    // Restore the state before adding the subforms = current state in DB
    var tempSubForms = term.SubForms;
    term.SubForms = null;

    // Inform EF about this state = term exists, subforms exist
    // in DB but no relationships
    db.Terms.Attach(term);
    foreach (var subForm in tempSubForms)
        db.SubForms.Attach(subForm);

    // Change the state: EF change tracking recognizes this
    term.SubForms = tempSubForms;

    //...

    // EF now will send INSERT statements for the join table
    db.SaveChanges();
    return term;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...