[英]Include calculated property in entity EF Core
我對數據模型進行了真正的代碼優先部署,並且我需要執行通常會與視圖相關聯的功能,但是目前尚不確定如何完成此功能。
為了簡化問題,我的模型具有注冊用戶創建和發布的內容,其他用戶可以與之交互。 我正在針對這些事物的流行程度設計一種算法,歸結為與交互類型乘以某個日期周期的倒數相關的加權因子。
例如,假設我們有“喜歡”,“評論”和“購買”,其權重分別為1、2和3。 假設我的時間是1周。 在這種情況下,三周前購買的商品在當前一周的重量為“贊”。
因此,模型的相關部分是具有主鍵和一些其他元數據的Thing
。 具有主鍵,權Weight
值和一些其他元數據的InteractionType
; 的Interaction
,其具有復合主鍵(由的Thing
主鍵, User
對象主鍵,並且InteractionType
主鍵)和一個DateValue
柱和任何其它內容相關的元數據。
最終,我希望有一種與實體框架兼容的方式來執行以下查詢:
;WITH InteractionScore
AS
(
SELECT t.Id ThingId, SUM(it.Weight/CAST(DATEDIFF(wk, i.DateValue, GETDATE()) AS float)) IntScore
FROM Things t
INNER JOIN Interactions i ON t.Id = i.ThingId
INNER JOIN InteractionTypes it ON i.InteractionTypeId = it.Id
GROUP BY t.ID
)
SELECT TOP(10) t.*
FROM Things t
LEFT JOIN InteractionScore isc ON t.Id = isc.ThingId
ORDER BY ISNULL(isc.IntScore, 0.0) DESC
數據模型類的定義如下:
namespace Project.Entities
{
public class User
{
[Key]
public int Id {get; set;}
public string IdentityRef {get;set;}
public string DisplayName {get;set;}
[InverseProperty("Owner")]
public ICollection<Thing> OwnedThings {get; set;}
}
public class InteractionType
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public double Weight { get; set; }
}
public class Thing
{
[Key]
public int Id {get;set;}
public int OwnerId {get; set;}
[ForeignKey("OwnerId")]
public User Owner {get; set;}
public string Summary {get; set;}
public string Description {get; set;}
public ICollection<Interaction> Interactions {get;set;}
}
public class Interaction
{
public int ThingId { get; set; }
public int UserId { get; set; }
public int InteractionTypeId {get; set;}
public Thing Thing {get; set;}
public User User {get;set;}
public InteractionType InteractionType {get;set;}
public DateTime DateValue {get;set;}
public string Comment {get; set;}
public string PurchaseReference {get;set;}
}
}
消費應用程序中的DbContext定義
namespace Project.Consumer
{
public class ApplicationData : DbContext
{
public DbSet<User> Users {get;set;}
public DbSet<Thing> Things {get;set;}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Interaction>()
.HasKey(i => new {i.ThingId, i.UserId, i.InteractionTypeId});
}
}
public List<Thing> GetMostPopularThings(ApplicationData ctx)
{
return ctx.Things.OrderByDescending(lambdaMagic).Take(10).ToList();
}
}
lambdaMagic當然是貪吃蛇了,但是正如我說的,我不確定是否有記錄的方式來做到這一點,而我只是想念它還是什么。 我已經看到了按照ctx.Things.FromSql("select string or sp here").Take(10).ToList();
也許還可以,但是我真的想減少項目外部存在的事物的數量(例如SP定義)
自編寫此問題以來,我繼續創建了另一個名為ThingStatistics的模型類:
public class ThingStatistics
{
[Key]
public int ThingId {get; set;}
[ForeignKey("ThingId")]
public Thing Thing {get; set;}
public double InteractionScore {get;set;}
}
然后,我對Thing類進行了如下擴充:
public class Thing
{
[Key]
public int Id {get;set;}
public int OwnerId {get; set;}
[ForeignKey("OwnerId")]
public User Owner {get; set;}
public string Summary {get; set;}
public string Description {get; set;}
public ICollection<Interaction> Interactions {get;set;}
public ThingStatistics Stats {get;set;}
}
我執行了Add-Migration步驟,然后按如下所示更改了結果Up / Down:
public partial class AggregationHack : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("GO; CREATE VIEW ThingStatistics AS SELECT t.ID ThingId, ISNULL(it.Weight/CAST(DATEDIFF(wk, i.DateValue, GETDATE()) + 1 AS float), 0) InteractionScore FROM Things t LEFT JOIN Interactions i INNER JOIN InteractionTypes it ON i.InteractionTypeId = it.Id ON t.ID = i.ThingId GROUP BY t.Id; GO;");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DROP VIEW ThingStatistics; GO;");
}
}
所以,現在我可以做ctx.Things.Include(t => t.Stats).OrderByDescending(t => t.Stats.InteractionScore).Take(10).ToList()
了,但是我不知道如果那是正確的,因為感覺像是這樣的黑客...
ORM的想法是,聯接大部分被導航屬性代替。 所以您的基本C#查詢看起來像
ctx.Things
.Include(t => t.Interactions).ThenInclude(i => i.InteractionType)
.Select(t => new {
t.ThingId,
IntScore = t.Interactions.Sum(i => i.InteractionType.Weight / ...)
})
.OrderBy(x => x.IntScore)
.Select(x => x.ThingId)
.Take(10);
在這些...
您需要替換DateDiff(NuGet上有一個第三方pkg)。
盡管這更簡單,更易讀,但以這種方式影響查詢的性能卻更加困難,但您必須進行測試。 您的SQL解決方案可能還不錯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.