LINQ:从左连接填充对象

我是linq的新手。 如何使用左连接数据库查询(PostGIS)中的LINQ加载对象。

这是我的数据库查询:

SELECT dt.id, dt.type, dta.id as "AttId", dta.label, dtav.id as "AttValueId", dtav.value FROM public."dataTypes" dt, public."dataTypeAttributes" dta LEFT JOIN public."dataTypeAttributeValues" dtav ON dta.id = "dataTypeAttributeId" WHERE dt.id = dta."dataTypeId" ORDER BY dt.type, dta.label, dtav.value 

这是示例输出:

在此处输入图像描述

我有3个实体:

 public class TypeData { public int ID { get; set; } public string Type { get; set; } public TypeDataAttribute[] Attributes { get; set; } } public class TypeDataAttribute { public int ID { get; set; } public string Label { get; set; } public TypeDataAttributeValue[] Values { get; set; } } public class TypeDataAttributeValue { public int ID { get; set; } public string Value { get; set; } } 

更新

这是我被卡住的地方:

 ... using (NpgsqlDataReader reader = command.ExecuteReader()) { if (reader.HasRows) { IEnumerable typeData = reader.Cast() .GroupJoin( //<--stuck here. } ... 

解:

使用@DavidB答案,这就是我的对象:

 using (NpgsqlDataReader reader = command.ExecuteReader()) { if (reader.HasRows) { var groups = reader.Cast() .GroupBy(dr => new { ID = (int)dr["id"], AttID = (int)dr["AttId"] }) .GroupBy(g => g.Key.ID); typeDataList = ( from typeGroup in groups let typeRow = typeGroup.First().First() select new TypeData() { ID = (int) typeRow["id"], Type = (string) typeRow["type"], Attributes = ( from attGroup in typeGroup let attRow = attGroup.First() select new TypeDataAttribute() { ID = (int)attRow["AttId"], Label = (string)attRow["label"], PossibleValues = ( from row in attGroup where !DBNull.Value.Equals(attRow["AttValueId"]) select new TypeDataAttributeValue() { ID = (int)row["AttValueId"], Value = (string)row["value"] } ).ToArray() } ).ToArray() } ); } } 

所以 – 如果我理解正确 – 你有一个你满意的数据库查询,但你想采用行列形结果并将其投影到一个分层结构的结果中。


假设结果在List

 public class Row { public int id {get;set;} public string type {get;set;} public int attid {get;set;} public string label {get;set;} public int? attvalueid {get;set;} public string value {get;set;} } 

然后,您将分组两次,并将每个顶级组转换为Type ,将每个子级别组转换为Attribute ,将每行转换为Value (如果该行不是空值)。

 List queryResult = GetQueryResult(); //make our hierarchies. var groups = queryResult .GroupBy(row => new {row.id, row.attid}) .GroupBy(g => g.Key.id); //now shape each level List answer = ( from typeGroup in groups let typeRow = typeGroup.First().First() select new Type() { id = typeRow.id, type = typeRow.type, Attributes = ( from attGroup in typeGroup let attRow = attGroup.First() select new Attribute() { id = attRow.attid, label = attRow.label Values = ( from row in attRow where row.attvalueid.HasValue //if no values, then we get an empty array select new Value() {id = row.attvalueid, value = row.value } ).ToArray() } ).ToArray() } ).ToList(); 
  var q = (from dt in public."dataTypes" // Join the second table to the first, using the IDs of the two tables <-- You may join on different columns from the two tables join dta in public."dataTypeAttributes" on new { ID = dt.id } equals new { ID = dta.id } // Join the third table to the first, using the IDs of the two tables join dtav in public."dataTypeAttributeId" on new { ID = dt.id } equals new { ID = dtav.id } // Conditional statement where dt.id == dta."dataTypeId" // Order the results orderby dt.type, dta.label, dtav.value // Select the values into a new object (datObj is a created class with the below variables) select new datObj() { ID = dt.id, Type = dt.type, AttID = dta.id, Label = dta.label, AttValueID = dtav.id, AttValue = dtav.value }).ToList() 

这将按orderby语句指定的顺序返回与where语句匹配的List。

不完全是你需要的,但应该给你一个你应该做的事情的例子。

试试GroupJoin sytnax

常规内连接还有Join语法

此链接有一个组连接示例

Yopu应该检查一下: http ://codingsense.wordpress.com/2009/03/08/left-join-right-join-using-linq/