我是物體框架和 Linq 的新手。我正在使用 .Net Core 和 EF Core 5。到目前為止我喜歡它,但遇到了一些我正在努力解決的問題。這是我真正感到困惑和不理解的一個。
我在課堂上展示了一些產品。我有客戶在另一個類別中購買這些產品。每個客戶可能會在他們的業務中使用不同的名稱來稱呼我的一種產品,因此我需要允許他們定義用于我的產品的別名。
這是我的兩個父類(產品和客戶)
public class Product
{
public int Id {get; set;}
public Guid IdGuid {get; set;}
public string Name {get; set;}
}
public class Customer
{
public int Id {get; set;}
public Guid IdGuid {get; set;}
public string Name {get; set;}
}
在這些類中,我有一個 Id 列,資料庫使用它來實作參照完整性。我不會將此 Id 傳回給用戶。相反,每當用戶獲取這些物件之一時,他們都會回傳 Guid,以便他們可以唯一標識資料庫中的行。連接這兩個表的別名類如下:
public class ProductCustomerAlias
{
public Product Product {get; set;}
public Customer Customer {get; set;}
public string Alias {get; set;}
}
由于我需要資料庫表使用由 Product Id 和 Customer Id 組成的復雜鍵,因此我必須覆寫背景關系物件的 OnModelCreating 方法:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ProductCustomerAlias>()
.HasKey("ProductId", "CustomerId");
}
'''
This ends up creating a Database table that has the following structure (in Oracle)
'''
CREATE TABLE "RTS"."ProductCustomerAlias"
(
"ProductId" NUMBER(10,0),
"CustomerId" NUMBER(10,0),
"Alias" NVARCHAR2(100)
)
到現在為止還挺好。我現在有一個相交表來存盤別名,其中 ProductId 和 CustomerId 的主鍵都是 DB 背景關系中產品和客戶的鍵整數值。
所以我的下一步是開始創建從這些物件中檢索資料的 Repo 類。請記住,提交請求的最終用戶只能將 Product.IdGuid 和 Customer.IdGuid 傳遞給我,因為這是他們曾經擁有的全部。在我的 Repo 中,我有以下代碼:
public async Task<ProductCustomerAlias> GetProductCustomerAliasAsync(Guid pProductId, Guid pCustomerId)
{
var alias = await (from ali in _context.ProductCustomerAlias
join prod in _context.Products on ali.Product.Id equals prod.Id
join cust in _context.Customers on ali.Customer.Id equals cust.Id
where cust.IdGuid == pCustomerId && prod.IdGuid == pProductId
select new {Product = prod,
Customer = cust,
Alias = ali.Alias}
).FirstOrDefaultAsync();
return (IEnumerable<ProductCustomerAlias>)alias;
}
我的問題是它給了我以下錯誤:
Cannot convert type '<anonymous type: Models.Product Product, Models.Customer Customer, string Alias>' to 'System.Collections.Generic.IEnumerable<Models.ProductCustomerAlias>'
Please don't tell me that the error is telling me exactly what is wrong. I am sure it is but if I understood where I was screwing up I would not be wasting my time typing out this ridiculously long explanation. So how can I cast the results from my Linq query to the specified type? Is there something else I am doing wrong? Any help would be greatly appreciated.
uj5u.com熱心網友回復:
回答您的具體問題。
那么如何將 Linq 查詢的結果轉換為指定的型別呢?
不能,因為 LINQ 查詢結果是匿名型別,與所需的結果型別(具體物體型別)不兼容,因此無法轉換為匿名型別。
還有什么我做錯了嗎?
很抱歉這么說,但基本上一切都錯了。
Select不需要,因為所需的結果型別是被查詢物體的確切型別。即ali這里的變數
from ali in _context.ProductCustomerAlias
正是您所需要的結果(在應用過濾器和限制運算子之后)
- 也不需要手動連接,因為它們是由導航屬性自動提供的,即這里
join prod in _context.Products on ali.Product.Id equals prod.Id
的prod是完全一樣的東西ali.Product
- 嘗試將單個物件強制轉換為 enumerable 是錯誤的
return (IEnumerable<ProductCustomerAlias>)alias
即使alias變數的型別正確,這也會失敗,因為它是單個物件而不是集合。
因此,解決方案非常簡單 - 使用相應的DbSet,應用過濾器 ( Where),將結果限制為零或一 ( FirstOrDefault{Async}) 就完成了。
有一個小細節。由于您正在查詢和回傳完整物體,因此其導航屬性(如Product和Customer)被視為相關資料,并且不會由 EF Core 自動填充(加載)。您必須明確選擇加入,這稱為預先加載,并在官方 EF Core 檔案的加載相關資料部分進行了解釋(我還建議您熟悉導航屬性和整個關系概念)。簡單來說,這需要使用專門提供的稱為Include和 的EF Core 擴展方法ThenInclude。
綜上所述,解決方案是這樣的:
public async Task<ProductCustomerAlias> GetProductCustomerAliasAsync(
Guid pProductId, Guid pCustomerId)
{
return await _context.ProductCustomerAlias
.Include(a => a.Product)
.Include(a => a.Customer)
.Where(a => a.Customer.IdGuid == pCustomerId && a.Product.IdGuid == pProductId)
.FirstOrDefaultAsync();
}
您甚至可以使用對 的謂詞多載的單個呼叫替換最后兩行FirstOrDefaultAsync,但這不是必需的,因為它只是上述內容的快捷方式
return await _context.ProductCustomerAlias
.Include(a => a.Product)
.Include(a => a.Customer)
.FirstOrDefaultAsync(a => a.Customer.IdGuid == pCustomerId && a.Product.IdGuid == pProductId);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/328525.html
標籤:c# linq entity-framework-core
上一篇:查詢串列中的陣列的簡單程式
