Simple.Data Многие-ко-многим - PullRequest
       3

Simple.Data Многие-ко-многим

3 голосов
/ 29 февраля 2012

Итак, я работаю над упрощенным примером моей ожидаемой базы данных, которая имеет следующие таблицы:

Contractors: Id, ContractorName
Types: Id, TypeName
CoverageZips: ContractorId, Zip
TypesForContractors: ContractorId, TypeId

, где у подрядчиков может быть много почтовых индексов, типов и типов, а у почтовых индексов может быть много подрядчиков (многие ко многим).

Я пытаюсь:

  1. выполнить поиск подрядчиков по определенному почтовому индексу
  2. , а затем загрузить типы для этихподрядчики.

SQL для первой части, вероятно, будет выглядеть так:

SELECT * FROM dbo.Contractors WHERE Id IN
(SELECT ContractorId FROM dbo.CoverageZips WHERE Zip = 12345)

Вот то, что у меня есть для первой части в Simple.Data.Это работает, но я чувствую, что мне не хватает всей красоты Simple.Data ...

List<int> contractorIds = new List<int>();
foreach(var coverage in _db.CoverageZips.FindAllByZip(zip)) {
    contractorIds.Add((int)coverage.ContractorId);
}
var contractors = new List<dynamic>();
if (contractorIds.Count > 0) {
    contractors = _db.Contractors.FindAllById(contractorIds).ToList<dynamic>();
}
return contractors;

Это работает нормально, пока я не попробую часть 2:

public dynamic GetAllForZip(int zip) {
    List<int> contractorIds = new List<int>();
    foreach(var coverage in _db.CoverageZips.FindAllByZip(zip)) {
        contractorIds.Add((int)coverage.ContractorId);
    }
    var contractors = new List<dynamic>();
    if (contractorIds.Count > 0) {
        contractors = _db.Contractors.FindAllById(contractorIds).ToList<dynamic>();
    }
    foreach (var contractor in contractors) {
        // Exception occurs here on second iteration
        // even though the second contractor was originally in the contractors variable
        contractor.types = GetTypesForContractor((int)contractor.Id);
    }
    return contractors;
}

public dynamic GetTypesForContractor(int id) {
    var types = new List<dynamic>();
    if (id > 0) {
        List<int> typeIds = new List<int>();
        foreach (var typeForContractor in _db.TypesForContractor.FindAllByContractorId(id)) {
            typeIds.Add((int)typeForContractor.TypeId);
        }

        if (typeIds.Count > 0) {
            types = _db.ContractorTypes.FindAllById(typeIds).ToList<dynamic>();
        }
    }
    return types;
}

Iустановите точку останова, и все работает нормально для первого показа итерации, но завершается сбоем на втором со следующим исключением:

Индекс был вне диапазона.Должен быть неотрицательным и меньше размера коллекции.

tl; dr

Я не уверен, как правильно использовать отношения многие ко многим с Simple.Data и чем-то подобнымстранно происходит, когда я пробую свой метод более одного раза

1 Ответ

5 голосов
/ 01 марта 2012

Я не знаю, что происходит с этим исключением, и проведу расследование сегодня.

Хотя вам не хватает красоты. Если в вашей базе данных настроена ссылочная целостность (что, конечно, вы делаете;)), ваши методы можно записать так:

public dynamic GetAllForZip(int zip) {
    var contractors = _db.Contractors
        .FindAll(_db.Contractors.ContractorZips.Zip == zip)
        .ToList();

    foreach (var contractor in contractors) {
        contractor.Types = GetTypesForContractor((int)contractor.Id);
    }
    return contractors;
}

public dynamic GetTypesForContractor(int id) {
    return _db.ContractorTypes
        .FindAll(_db.ContractorTypes.TypesForContractor.ContractorId == id)
        .ToList();
}

Обновление!

Начиная с версии 1.0.0-бета3 поддерживается энергичная загрузка через объединения «многие ко многим», поэтому теперь вы можете сделать это:

public dynamic GetAllForZip(int zip) {
    return _db.Contractors
        .FindAll(_db.Contractors.ContractorZips.Zip == zip)
        .With(_db.Contractors.TypesForContractor.ContractorTypes.As("Types"))
        .ToList();
}

И это выполняется в виде единого выбора SQL, чтобы сделать вашего администратора БД счастливым, как радужные котята.

...