从加入的 table 中选择 OrmLite 新对象进行插入
Selecting OrmLite new object from joined table for insertion
我有 3 个实体:
[CompositeIndex(nameof(Url), nameof(TargetDomainRecordId), nameof(UserAuthCustomId), Unique = true)]
public class WatchedUrlRecord
{
[AutoIncrement]
public long Id { get; set; }
public string Url { get; set; }
public string Provider { get; set; }
public string DomainKey { get; set; }
public WatchedUrlScanStatus WatchedUrlScanStatus { get; set; }
public bool NoFollow { get; set; }
public HttpStatusCode HttpStatusCode { get; set; }
public DateTime? LastScanTime { get; set; }
public WatchedUrlScanResult LastScanData { get; set; }
public string Anchors { get; set; }
public int? OutboundLinks { get; set; }
[ForeignKey(typeof(TargetDomainRecord), OnDelete = "CASCADE")]
public long TargetDomainRecordId { get; set; }
[ForeignKey(typeof(UserAuthCustom), OnDelete = "CASCADE")]
public long UserAuthCustomId { get; set; }
}
[CompositeIndex(nameof(Url), nameof(TargetDomainRecordId), nameof(UserAuthCustomId), Unique = true)]
public class WatchedUrlQueue
{
[PrimaryKey]
public long WatchedUrlRecordId { get; set; }
[Index]
public string Url { get; set; }
[Index]
public string DomainKey { get; set; }
[Index]
public long TargetDomainRecordId { get; set; }
public string TargetDomainKey { get; set; }
[Index]
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
public int Tries { get; set; }
[Index]
public DateTime? DeferUntil { get; set; }
[Index]
public long UserAuthCustomId { get; set; }
[Index]
public bool FirstScan { get; set; }
}
[CompositeIndex(nameof(Url), nameof(UserAuthCustomId), Unique = true)]
public class TargetDomainRecord
{
[AutoIncrement]
public long Id { get; set; }
public string Url { get; set; }
public string DomainKey { get; set; }
public DateTime CreateDate { get; set; } = DateTime.Now;
public DateTime? DeleteDate { get; set; }
public bool IsDeleted { get; set; }
public bool Active { get; set; } = true;
public DomainType DomainType { get; set; }
[ForeignKey(typeof(UserAuthCustom), OnDelete = "CASCADE")]
public long UserAuthCustomId { get; set; }
}
我试图根据 WatchedUrlRecords 的 ID 插入队列对象,所以我想出了这个查询:
var q = db.From<WatchedUrlRecord>()
.Where(x => Sql.In(x.Id, ids))
.Join<TargetDomainRecord>((w, t) => w.TargetDomainRecordId == t.Id)
.Select<WatchedUrlRecord, TargetDomainRecord>((w, t) => new WatchedUrlQueue()
{
UserAuthCustomId = w.UserAuthCustomId,
DomainKey = w.DomainKey,
CreateDate = DateTime.UtcNow,
DeferUntil = null,
FirstScan = firstScan,
TargetDomainKey = t.DomainKey,
Tries = 0,
TargetDomainRecordId = w.TargetDomainRecordId,
Url = w.Url,
WatchedUrlRecordId = w.Id
});
var inserted = db.InsertIntoSelect<WatchedUrlQueue>(q, dbCmd => dbCmd.OnConflictIgnore());
这不起作用并给出错误:
variable 'w' of type 'Project.ServiceModel.WatchedUrl.Entities.WatchedUrlRecord' referenced from scope '', but it is not defined
如果我尝试像 new {}
这样的匿名对象而不是 new WatchedUrlQueue
那么 InsertIntoSelect()
会抛出错误:
'watched_url_record"."user_auth_custom_id' is not a property of 'WatchedUrlQueue'
我查看了文档并且可以看到 SelectMulti()
方法,但我认为这不合适,因为它需要我创建一个元组列表以合并到新对象中。传递的列表可能非常大,所以我只想将正确的 SQL 语句发送到 PostgreSQL,这将沿着以下行:
insert into watched_url_queue (watched_url_record_id, url, domain_key, target_domain_record_id, target_domain_key, create_date, tries, defer_until, user_auth_custom_id)
select wur.id watched_url_record_id,
wur.url url,
wur.domain_key,
wur.target_domain_record_id,
tdr.domain_key,
'{DateTime.UtcNow:MM/dd/yyyy H:mm:ss zzz}' create_date,
0 tries,
null defer_until,
wur.user_auth_custom_id
from watched_url_record wur
join target_domain_record tdr on wur.target_domain_record_id = tdr.id
where wur.id in (323,3213123,312312,356456)
on conflict do nothing ;
我目前在我的应用程序中有很多类似类型的查询,这导致了维护它们的额外工作,能够让它们在不降低性能的情况下流畅地使用 api 真是太好了。这可能吗?
自定义 select 表达式不能是类型化投影(即 x => new MyType { ... }
),即您需要使用匿名类型表达式(即 new { ... }
)来捕获您的查询的自定义 SELECT 投影表达式。
您还需要将 JOIN 表达式直接放在 FROM 之后(如 SQL 中所做的那样),这告诉 OrmLite 它需要完全限定后续的列表达式,例如 Id
,否则会产生歧义.
我已经解决了 this commit 中自定义 select 表达式的字段解析问题,您的查询现在应该按预期工作了:
var q = db.From<WatchedUrlRecord>()
.Join<TargetDomainRecord>((w, t) => w.TargetDomainRecordId == t.Id)
.Where(x => Sql.In(x.Id, ids))
.Select<WatchedUrlRecord, TargetDomainRecord>((w, t) => new {
UserAuthCustomId = w.UserAuthCustomId,
DomainKey = w.DomainKey,
CreateDate = DateTime.UtcNow,
DeferUntil = (DateTime?) null,
FirstScan = firstScan,
TargetDomainKey = t.DomainKey,
Tries = 0,
TargetDomainRecordId = w.TargetDomainRecordId,
Url = w.Url,
WatchedUrlRecordId = w.Id
});
var inserted = db.InsertIntoSelect<WatchedUrlQueue>(q, dbCmd=>dbCmd.OnConflictIgnore());
此更改适用于 v5.10.5,即现在 available on MyGet。
我有 3 个实体:
[CompositeIndex(nameof(Url), nameof(TargetDomainRecordId), nameof(UserAuthCustomId), Unique = true)]
public class WatchedUrlRecord
{
[AutoIncrement]
public long Id { get; set; }
public string Url { get; set; }
public string Provider { get; set; }
public string DomainKey { get; set; }
public WatchedUrlScanStatus WatchedUrlScanStatus { get; set; }
public bool NoFollow { get; set; }
public HttpStatusCode HttpStatusCode { get; set; }
public DateTime? LastScanTime { get; set; }
public WatchedUrlScanResult LastScanData { get; set; }
public string Anchors { get; set; }
public int? OutboundLinks { get; set; }
[ForeignKey(typeof(TargetDomainRecord), OnDelete = "CASCADE")]
public long TargetDomainRecordId { get; set; }
[ForeignKey(typeof(UserAuthCustom), OnDelete = "CASCADE")]
public long UserAuthCustomId { get; set; }
}
[CompositeIndex(nameof(Url), nameof(TargetDomainRecordId), nameof(UserAuthCustomId), Unique = true)]
public class WatchedUrlQueue
{
[PrimaryKey]
public long WatchedUrlRecordId { get; set; }
[Index]
public string Url { get; set; }
[Index]
public string DomainKey { get; set; }
[Index]
public long TargetDomainRecordId { get; set; }
public string TargetDomainKey { get; set; }
[Index]
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
public int Tries { get; set; }
[Index]
public DateTime? DeferUntil { get; set; }
[Index]
public long UserAuthCustomId { get; set; }
[Index]
public bool FirstScan { get; set; }
}
[CompositeIndex(nameof(Url), nameof(UserAuthCustomId), Unique = true)]
public class TargetDomainRecord
{
[AutoIncrement]
public long Id { get; set; }
public string Url { get; set; }
public string DomainKey { get; set; }
public DateTime CreateDate { get; set; } = DateTime.Now;
public DateTime? DeleteDate { get; set; }
public bool IsDeleted { get; set; }
public bool Active { get; set; } = true;
public DomainType DomainType { get; set; }
[ForeignKey(typeof(UserAuthCustom), OnDelete = "CASCADE")]
public long UserAuthCustomId { get; set; }
}
我试图根据 WatchedUrlRecords 的 ID 插入队列对象,所以我想出了这个查询:
var q = db.From<WatchedUrlRecord>()
.Where(x => Sql.In(x.Id, ids))
.Join<TargetDomainRecord>((w, t) => w.TargetDomainRecordId == t.Id)
.Select<WatchedUrlRecord, TargetDomainRecord>((w, t) => new WatchedUrlQueue()
{
UserAuthCustomId = w.UserAuthCustomId,
DomainKey = w.DomainKey,
CreateDate = DateTime.UtcNow,
DeferUntil = null,
FirstScan = firstScan,
TargetDomainKey = t.DomainKey,
Tries = 0,
TargetDomainRecordId = w.TargetDomainRecordId,
Url = w.Url,
WatchedUrlRecordId = w.Id
});
var inserted = db.InsertIntoSelect<WatchedUrlQueue>(q, dbCmd => dbCmd.OnConflictIgnore());
这不起作用并给出错误:
variable 'w' of type 'Project.ServiceModel.WatchedUrl.Entities.WatchedUrlRecord' referenced from scope '', but it is not defined
如果我尝试像 new {}
这样的匿名对象而不是 new WatchedUrlQueue
那么 InsertIntoSelect()
会抛出错误:
'watched_url_record"."user_auth_custom_id' is not a property of 'WatchedUrlQueue'
我查看了文档并且可以看到 SelectMulti()
方法,但我认为这不合适,因为它需要我创建一个元组列表以合并到新对象中。传递的列表可能非常大,所以我只想将正确的 SQL 语句发送到 PostgreSQL,这将沿着以下行:
insert into watched_url_queue (watched_url_record_id, url, domain_key, target_domain_record_id, target_domain_key, create_date, tries, defer_until, user_auth_custom_id)
select wur.id watched_url_record_id,
wur.url url,
wur.domain_key,
wur.target_domain_record_id,
tdr.domain_key,
'{DateTime.UtcNow:MM/dd/yyyy H:mm:ss zzz}' create_date,
0 tries,
null defer_until,
wur.user_auth_custom_id
from watched_url_record wur
join target_domain_record tdr on wur.target_domain_record_id = tdr.id
where wur.id in (323,3213123,312312,356456)
on conflict do nothing ;
我目前在我的应用程序中有很多类似类型的查询,这导致了维护它们的额外工作,能够让它们在不降低性能的情况下流畅地使用 api 真是太好了。这可能吗?
自定义 select 表达式不能是类型化投影(即 x => new MyType { ... }
),即您需要使用匿名类型表达式(即 new { ... }
)来捕获您的查询的自定义 SELECT 投影表达式。
您还需要将 JOIN 表达式直接放在 FROM 之后(如 SQL 中所做的那样),这告诉 OrmLite 它需要完全限定后续的列表达式,例如 Id
,否则会产生歧义.
我已经解决了 this commit 中自定义 select 表达式的字段解析问题,您的查询现在应该按预期工作了:
var q = db.From<WatchedUrlRecord>()
.Join<TargetDomainRecord>((w, t) => w.TargetDomainRecordId == t.Id)
.Where(x => Sql.In(x.Id, ids))
.Select<WatchedUrlRecord, TargetDomainRecord>((w, t) => new {
UserAuthCustomId = w.UserAuthCustomId,
DomainKey = w.DomainKey,
CreateDate = DateTime.UtcNow,
DeferUntil = (DateTime?) null,
FirstScan = firstScan,
TargetDomainKey = t.DomainKey,
Tries = 0,
TargetDomainRecordId = w.TargetDomainRecordId,
Url = w.Url,
WatchedUrlRecordId = w.Id
});
var inserted = db.InsertIntoSelect<WatchedUrlQueue>(q, dbCmd=>dbCmd.OnConflictIgnore());
此更改适用于 v5.10.5,即现在 available on MyGet。