Может ли EF4.1 Code First одновременно выразить 1-1 и 1-много в одной и той же таблице?

Проблема высокого уровня: я хотел бы получить быстрый поиск по таблице, к которой у меня отношение 1-многие.

У меня есть большая журнальная таблица с внешним ключом для таблицы сотрудников. Я хотел бы иметь отношение из таблицы сотрудников к самой последней записи в журнале (для этого сотрудника), а также к регулярной коллекции многих записей журнала. Я мог бы использовать только один ко многим и просто запросить последнюю метку времени и идентификатор сотрудника в лог-файле, но я бы предпочел прямой указатель.

Можно ли сделать что-то подобное с аннотациями?

public class TagEntry
{
    public int TagEntryId { get; set; }

    public int TagId { get; set; }
    public DateTime LogTime { get; set; }
    public string log { get; set; }

    public virtual Tag tag { get; set; }
}

public class Tag
{

    public int TagId { get; set; }
    public TagEntry CurrentTagEntry { get; set; }
    public int TagEntryId { get; set; }

    public string someTagData { get; set; }
    public virtual ICollection<TagEntry> TagEntries { get; set; }
}

Одним из решений было бы просто сохранить целочисленный currentTagEntryId, но в идеале я бы хотел сослаться на Log с нотацией типа tag.CurrentTagEntry.log.

1 ответ

Решение

К сожалению, это невозможно с помощью картографирования. Ваш CurrentTagEntry представляет один к одному отношения между Tag а также TagEntry но в то же время у вас есть отношение один ко многим между Tag а также TagEntry, Сопоставление один-к-одному требует, чтобы оба объекта совместно использовали первичный ключ =>, чтобы иметь возможность отображать отношения один-к-одному. PK TagEntry должен быть FK для Tag, Это, очевидно, нарушит отношение один ко многим.

Вы должны сделать это как вспомогательную функцию вместо отображения.

Например, это можно использовать как вспомогательный запрос linq:

var lastLog = (from te in context.TagEntries
               where te.TagId == id
               orderby te.LogTime descending
               select te).FirstOrDefault();

Или это как вспомогательная загрузка:

var entry = context.Entry<Tag>(tag);
if (!entry.Collection(t => t.TagEntries).IsLoaded)
{
    // Selective eager loading
    entry.Collection(t => t.TagEntries)
         .Query()
         .OrderByDescending(te => te.LogTime)
         .Take(1)
         .Load();
}

var tag = tag.TagEntries.FirstOrDefault();
Другие вопросы по тегам