一对多而不暴露模型中的子集合和/或外键

时间:2012-12-05 15:36:41

标签: c# orm dapper

当我没有在POCO模型中公开我的外键和子集时,我遇到了Dapper的问题。 让我们举两个实体的简单例子:

Bike (Id, ModelName)
Tire (Id, Tread)

在数据库中,每个Tire都有一个自行车的外键。但我的模型没有。 从数据库中,我想将此结构具体化为Dictionary<Bike, IEnumerable<Tire>>。每辆自行车(独一无二)将有两个轮胎。

我可以使用以下查询选择此一对多关系:

SELECT b.Id, b.ModelName, t.Id, t.Tread
FROM Bike b
JOIN Tire t ON b.Id = t.bike_id

为了使用Dapper进行映射,我已完成以下操作:

var dbResult = connection.Query<Bike, Tire, KeyValuePair<Bike, Tire>>("sql-query-above",
(a, s) => new KeyValuePair<Bike, Tire>(a, s);
splitOn: "Id");

使用LINQ:

将结果转换为我的字典
Dictionary<Bike, IEnumerable<Tire>> dict = dbResult.GroupBy(g => g.Key, g => g.Value).ToDictionary(g => g.Key, g => g.AsEnumerable());

它正确返回数据结构:

Bike #1
 - Tire #1
 - Tire #2
Bike #2
 - Tire #3
 - Tire #4

但这是实现此数据结构的最有效方式吗? 另一种方法是避免使用字典并创建暴露外键和关系的其他实体(例如Bike上的Tires集合和Tire上的FK),并使用像here所述的映射方法。 但我想在我的模型中避免这种情况,因为它会导致许多额外的类。但性能呢?这更糟还是一样?

1 个答案:

答案 0 :(得分:0)

我不是使用Dapper的专家,但我遇到了与你正在遇到的限制。我有一个类似的情况,我的对象中的一个属性是像你厌倦的集合。我发现创建第二个查询以使用扩展方法填充那些内部类型的集合更简单。

所以你可能先抓住所有的自行车,然后调用你的扩展方法来获取轮胎数据,如:

dict.WithTires();    

我知道这是对数据库的第二次调用,但权衡的是你仍然可以在不必每次都获取轮胎信息的情况下抓住自行车。

另外,您可能会考虑将轮胎集合作为属性添加到您的自行车类中,而恕我直言,恕我直言。如果您有这样的事情:

public class Bike
{
    public int id { get; set; }
    public string modelName { get; set; }
    public IList<Tires> tires { get; set; }
}

public class Tires
{
    public int id { get; set; }
    public string tread { get; set; }
}

您可以轻松创建一种扩展方法,用于抓取单个自行车或自行车系列的轮胎数据:

Bike myBike = new Bike();
List<Bike> bikeCollection = new List<Bike>();

myBike.WithTires();
bikeCollection.WithTires();