私が経験したLinqのこの動作を理解する必要があります。「パッケージ」をデータベースに保存しています。パッケージは親と子を持つことができるため、グラフ構造です。次の方法を使用して、ルート パッケージを取得します。次に、子とその子などを取得する必要があります。
ルートパッケージの取得方法
var rootPack = (from p in context.Packages
//several joins emitted for clarity
where p.PackageID == parentId
select new PackageModel
{
PackageId = p.PackageID,
TagId = p.TagID
//rest of the properties have been emitted for clarity
}).FirstOrDefault();
if (rootPack != null)
{
rootPack.Children = new List<PackageModel>();
var fullStructure = GetChildPackages(rootPack, rootPack);
}
次の方法で問題が発生しました。ここでは、動作中の形式です。
GetChildPackages - 作業フォーム
private PackageModel GetChildPackages(PackageModel package, PackageModel parentPackage = null)
{
var innerContext = new DbDataContext(ConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString);
var children = (from p in innerContext.Packages
//several joins emitted for clarity
where p.ParentPackageID == package.PackageId
select new PackageModel
{
PackageId = p.PackageID,
Parent = parentPackage,
//rest of the properties have been emitted for clarity
}).ToList();
//get all children
foreach (var child in children)
{
child.Children = new List<PackageModel>();
package.Children.Add(GetChildPackages(child, package));
}
return package;
}
選択した後、foreach ループで子の各子リストを初期化することに注意してください。以前は、他のすべてのプロパティを使用して、クエリで初期化していました。
この構造をロードするとしましょう:
ROOTPACKAGE
/ \
CHILD_A CHILD_B
/ |
CHILD_A1 CHILD_A2
リストしたコードはこの構造を問題なくロードしますが、Linq クエリで Children リストを初期化すると、地獄が壊れてしまいます。CHILD_B には子がない代わりに、CHILD_A1 と CHILD_A2 があります。CHILD_A にもこれらの子供がいます。デバッガーでは、CHILD_A の Children リストに追加するたびに、CHILD_B にも追加されていることがわかりました。各パッケージには固有のパッケージ ID があるため、パッケージがまったく同じではないことは確かです。Children リストへのポインターまたは参照が完全に混同されているようですが、これはなぜでしょうか? これに光を当ててくれてありがとう。