我是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> typeData = reader.Cast<System.Data.Common.DbDataRecord>()
.GroupJoin( //<--stuck here.
}
...
使用@DavidB答案,这就是我的对象:
using (NpgsqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
var groups = reader.Cast<System.Data.Common.DbDataRecord>()
.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()
}
);
}
}
答案 0 :(得分:2)
所以 - 如果我理解正确 - 你有一个你很满意的数据库查询,但是你想要获得行列形状的结果并将其投影到一个分层结构的结果中。
假设结果位于List<Row>
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<Row> 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<Type> 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();
答案 1 :(得分:1)
答案 2 :(得分:1)
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()
这将按照where
语句指定的顺序返回与orderby
语句匹配的List。
不完全符合您的要求,但应该举例说明您应该做些什么。
答案 3 :(得分:0)