У меня странная проблема с linq-to-sql, и я действительно пытался ее найти. Я проектирую базу данных sql и где только недавно пытался извлечь объект из нее.
Проблема с несколькими объединениями. Все мои таблицы используют в качестве первичных ключей столбцы идентификации.
ДБ разработан следующим образом:
MasterTable: Id (первичный ключ, столбец идентификаторов, int), MasterColumn1 (nvarchar (50))
Slave1: Id (первичный ключ, столбец идентификаторов, int), MasterId (int, первичный ключ -> Id MasterTable), SlaveCol1
Slave2: Id (первичный ключ, столбец идентификаторов, int), MasterId (int, первичный ключ -> Id MasterTable), SlaveColumn2
использованный код:
var db = new TestDbDataContext() { Log = Console.Out };
var res = from f in db.MasterTables
where f.MasterColumn1 == "wtf"
select new
{
f.Id,
SlaveCols1 = f.Slave1s.Select(s => s.SlaveCol1),
SlaveCols2 = f.Slave2s.Select(s => s.SlaveColumn2)
};
foreach (var re in res)
{
Console.Out.WriteLine(
re.Id + " "
+ string.Join(", ", re.SlaveCols1.ToArray()) + " "
+ string.Join(", ", re.SlaveCols2.ToArray())
);
}
И журнал:
SELECT [t0].[Id], [t1].[SlaveCol1], (
SELECT COUNT(*)
FROM [FR].[Slave1] AS [t2]
WHERE [t2].[MasterId] = [t0].[Id]
) AS [value]
FROM [FR].[MasterTable] AS [t0]
LEFT OUTER JOIN [FR].[Slave1] AS [t1] ON [t1].[MasterId] = [t0].[Id]
WHERE [t0].[MasterColumn1] = @p0
ORDER BY [t0].[Id], [t1].[Id]
-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [wtf]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.5420
SELECT [t0].[SlaveColumn2]
FROM [FR].[Slave2] AS [t0]
WHERE [t0].[MasterId] = @x1
-- @x1: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.5420
1 SlaveCol1Wtf SlaveCol2Wtf
Почему бы не сделать два внешних соединения? Я действительно беспокоюсь об этом, потому что у меня есть намного большая база данных со многими таблицами, ссылающимися на одну и ту же таблицу (все имеют отношение один ко многим), и наличие 20 выборок циклических обращений к серверу базы данных не является оптимальным!
Как я отмечу. Я могу получить желаемый результат, используя явные внешние соединения следующим образом:
var db = new TestDbDataContext() { Log = Console.Out };
var res = from f in db.MasterTables
join s1 in db.Slave1s on f.Id equals s1.MasterId into s1Tbl
from s1 in s1Tbl.DefaultIfEmpty()
join s2 in db.Slave2s on f.Id equals s2.MasterId into s2Tbl
from s2 in s2Tbl.DefaultIfEmpty()
where f.MasterColumn1 == "wtf"
select new { f.Id, s1.SlaveCol1, s2.SlaveColumn2 };
foreach (var re in res)
{
Console.Out.WriteLine(re.Id + " " + re.SlaveCol1 + " " + re.SlaveColumn2);
}
Но я хочу использовать ссылки, которые предоставляет Linq-To-Sql, а не ручные соединения! Как?
----------- редактировать -----------------
Я также пытался выполнить предварительную выборку так:
using (new DbConnectionScope())
{
var db = new TestDbDataContext() { Log = Console.Out };
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<MasterTable>(c => c.Slave1s);
loadOptions.LoadWith<MasterTable>(c => c.Slave2s);
db.LoadOptions = loadOptions;
var res = from f in db.MasterTables
where f.MasterColumn1 == "wtf"
select f;
foreach (var re in res)
{
Console.Out.WriteLine(re.Id + " " +
string.Join(", ", re.Slave1s.Select(s => s.SlaveCol1).ToArray()) + " " +
string.Join(", ", re.Slave2s.Select(s => s.SlaveColumn2).ToArray()));
}
}
тот же результат = (