【发布时间】:2021-06-19 20:46:59
【问题描述】:
在sqlite中,有一个表叫pathparts,这个表包含3列
rowId | parent | pathpart
行如下
rowId | parent | pathpart
--------------------------
1 | null | manifests
100 | 1 | h
154 | 100 | publisher
184 | 154 | appname
654 | 184 | version
985 | 654 | url
1452 | 1 | f
1460 | 1452 | publisher
2456 | 1460 | appname
3456 | 2456 | url
如您所见,每一行都包含一个父行,它将其连接到另一行并且它们最终都连接到父级 1(这是 Winget 软件的 Microsoft database)如果我们将这些行按顺序放在一起,它会创建一个包的规格,例如:
h\microsoft\vscode\1.0.1.0\url.yml
我可以使用以下代码提取此信息
var query =
from item in msixDB.IdsMSIXTable
from manifest in msixDB.Set<ManifestMSIXTable>().Where(e => e.id == item.rowid)
from yml in msixDB.PathPartsMSIXTable.Where(e => e.rowid == manifest.pathpart).Take(1).DefaultIfEmpty()
from pathPartVersion in msixDB.PathPartsMSIXTable.Where(e => e.rowid == yml.parent).Take(1).DefaultIfEmpty()
from pathPartAppName in msixDB.PathPartsMSIXTable.Where(e => e.rowid == pathPartVersion.parent).Take(1).DefaultIfEmpty()
from pathPartPublisher in msixDB.PathPartsMSIXTable.Where(e => e.rowid == pathPartAppName.parent).Take(1).DefaultIfEmpty()
from pathPart in msixDB.PathPartsMSIXTable.Where(e => e.rowid == pathPartPublisher.parent).Take(1).DefaultIfEmpty()
from version in msixDB.VersionsMSIXTable.Where(e => e.rowid == manifest.version).Take(1).DefaultIfEmpty()
select new ManifestTable
{
PackageId = item.id,
YamlName = $@"{pathPart.pathpart}\{pathPartPublisher.pathpart}\{pathPartAppName.pathpart}\{pathPartVersion.pathpart}\{yml.pathpart}",
Version = version.version
};
mydb.ManifestTable.AddRange(await query.ToListAsync());
但问题是这些行没有固定的编号,所以我写的代码不起作用。 例如,在上表中,如您所见,其中一个包包含 4 行,另一个包含 3 行。 我需要一种方法来跟踪父行以到达父 1 并提取信息。
更新:
[Table("pathparts")]
public class PathPartsMSIXTable
{
[Key]
public long rowid { get; set; }
public long parent { get; set; }
public string pathpart { get; set; }
}
更新 2:
我稍微修改了你写的代码,结果如下
from manifest in msixDB.Set<ManifestMSIXTable>().Where(e => e.id == item.rowid)
from yml in msixDB.PathPartsMSIXTable.Where(e => e.rowid == manifest.pathpart)
from pathPart in pathCte.Where(e => e.rowid == yml.parent && e.parent == null)
from version in msixDB.VersionsMSIXTable.Where(e => e.rowid == manifest.version)
select new ManifestTable
{
PackageId = item.id,
YamlName = $@"{pathPart.path}\{yml.pathpart}",
Version = version.version
};
现在一切正常,除了一些行没有添加
微软数据库
将项目添加到数据库后
如您所见,只添加了 1 行
更新 3
我注意到有些项目是重复存储在数据库中的,如何防止基于 ID 和版本号的重复信息? 我使用了 Distinct 方法,但出现错误
System.AggregateException: 'One or more errors occurred. (Sequence 'value(LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsDataConnection).GetTable().SelectMany(item => value(LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsDataConnection).GetTable().Where(e => (e.id == item.rowid)), (item, manifest) => new <>f__AnonymousType0`2(item = item, manifest = manifest)).SelectMany(<>h__TransparentIdentifier0 => value(LinqToDB.EntityFrameworkCore.LinqToDBForEFToolsDataConnection).GetTable().Where(e => (e.rowid == <>h__TransparentIdentifier0.manifest.pathpart)), (<>h__TransparentIdentifier0, yml) => new <>f__AnonymousType1`2(<>h__TransparentIdentifier0 = <>h__TransparentIdentifier0, yml = ...
query = query.Distinct(new GenericCompare<ManifestTable>(x => x.PackageId));
var data = await query.ToArrayAsyncLinqToDB();
mydb.AddRange(data);
【问题讨论】:
-
我感觉你为你的任务选择了糟糕的 ORM。对于这种情况,您需要 CTE。如果你OK,我会准备这个扩展的示例:github.com/linq2db/linq2db.EntityFrameworkCore,注意我是这个扩展的创建者。
-
@SvyatoslavDanyliv 我对数据库的工作不多,所以我做得不够,我很好
-
你能用
PathPartsMSIXTable类定义更新问题吗? -
@SvyatoslavDanyliv 完成