Реализация таблицы на иерархию с использованием Entity Framework и шаблона репозитория - PullRequest
2 голосов
/ 28 ноября 2010

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

public Document Load(Guid firmId, int prettyId)
{
    // the OfType<> can be OfType<Page>, OfType<Blog>, ...
    var instance = (from c in _ctx.Documents.OfType<X>() where c.firm_id == firmId && c.PrettyId == prettyId select c).FirstOrDefault();
    ...
}

У меня есть только один класс, который реализует репозиторий, и он использует Document в качестве типа для возврата из методов. Мне не нужны пользовательские реализации для различных типов, которые происходят от Document, потому что особенности реализации для загрузки, вставки и обновления одинаковы для всех. Мне просто нужно определить / предоставить тип методам, с которыми мы хотим работать.

Надеюсь, вы поймете, что я имею в виду. Пожалуйста, не отвечайте со ссылками на то, как смоделировать TPH, потому что я уже сделал это, и он смоделирован хорошо.

Ответы [ 2 ]

1 голос
/ 28 ноября 2010

Я действительно обнаружил, что мне не нужно обнаружение во время выполнения, потому что я могу предоставить тип во время компиляции в моих контроллерах MVC, которые, в отличие от репозитория (который только один), зависят от типа (у меня есть PageController, BlogController и т.д. .) вот так:

public virtual ActionResult Print(int prettyId)
{
    //Document invoice = _repository.Load(prettyId, _docType);
    Document invoice = _repository.Load<Invoice>(prettyId);
    ...
}

В моем интерфейсе репозитория теперь есть следующее:

// also, please comment, which one is better, this one?
T Load<T>(int prettyId) where T : Document;
T Load<T>(Guid firmId, int prettyId) where T : Document;

// or this one?
//T Load<T1>(int prettyId) where T1 : Document;
//T Load<T1>(Guid firmId, int prettyId) where T1 : Document;

и в реализации репозитория у меня это:

public T Load<T>(int prettyId) where T : Document
{
    return Load<T>(AppState.FirmId, prettyId);
}

public T Load<T>(Guid firmId, int prettyId) where T : Document
{
    var instance =
        (from c in _ctx.Documents.OfType<T>()
         where c.firm_id == firmId && c.PrettyId == prettyId
         select c).FirstOrDefault();
    instance.FirmReference.Load();
    instance.ClientReference.Load();
    instance.DocumentItems.Load();
    instance.TaxStatementReference.Load();
    return instance;
}

Это работает и выглядит довольно мило.

0 голосов
/ 28 ноября 2010

Простой способ - создать отдельный метод для каждого специального типа документа, который вы хотите загрузить, или использовать операторы switch / case с некоторым дискриминатором в качестве параметра в методе Load. Я понимаю, что вы хотите избежать такого решения. В этом случае вы должны попытаться использовать рефлексию, потому что предоставление универсального параметра типа во время выполнения невозможно. Проверьте этот ответ для вызова универсального метода с отражением. Вы вызовете базовый запрос с OfType и получите экземпляр IQueryalbe, который будет использоваться для второй части запроса с условиями where.

...