3

所以我正在研究一个我希望的数据库的简化示例,它具有以下表格:

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;
}

我设置了一个断点,第一次迭代显示一切正常,但第二次失败,出现以下异常:

指数超出范围。必须是非负数且小于集合的大小。

tl;博士

我不确定如何正确使用 Simple.Data 的多对多关系,并且当我多次尝试我的方法时发生了一些奇怪的事情

4

1 回答 1

5

我不知道该异常发生了什么,今天将进行调查。

不过,你错过了一些美丽。假设您在数据库上配置了引用完整性(当然您这样做了;)),您的方法可以这样编写:

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-beta3 开始,支持跨多对多连接的即时加载,所以现在您可以这样做:

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

它作为单个 SQL 选择执行,让您的 DBA 像彩虹小猫一样开心。

于 2012-03-01T10:14:25.120 回答