[英]Join two lists returns IEnumerable in IEnumerable C# Entity framework
我試圖加入兩個列表,但是當我只希望簡單的列表時,結果給我一個IEnumerable中的IEnumerable。 我可以將兩個IEnumerables都強制轉換為列表,但是林先生困惑為什么首先發生這種情況。 為什么會這樣?為了從聯接中僅獲取一個列表,我需要做什么?
namespace arena.DAL
{
public class EquipmentData
{
private Arena db = new Arena();
public ArmorModel getArmor()
{
var user = UserData.getCurrentUser();
var equipmentArmorList = db.EquipmentModels.Where(e => e.AccountId == user.Id && e.EquipmentType == (int)Constants.EquipmentConstants.EquipmentType.Armor).ToList();
var armorList = db.ArmorModels.ToList();
var result = from f in equipmentArmorList
join s in armorList
on f.EquipmentId equals s.Id into g
select g.ToList();
return result;
}
}
}
public class EquipmentModel
{
public EquipmentModel()
{
}
public int Id { get; set; }
public string AccountId { get; set; }
public int EquipmentId { get; set; }
public int EquipmentType { get; set; }
public bool Equipped { get; set; }
}
public class ArmorModel
{
public ArmorModel()
{
}
public int Id { get; set; }
public int Level { get; set; }
public string Name { get; set; }
public string Biographi { get; set; }
public double Health { get; set; }
public double Stamina { get; set; }
public double Strength { get; set; }
public double Initiative { get; set; }
public double Avoidance { get; set; }
public double Armor { get; set; }
public double Durability { get; set; }
public int MinDamage { get; set; }
public int MaxDamage { get; set; }
public int ExperienceGain { get; set; }
public int CurrencyGain { get; set; }
public int Cost { get; set; }
public int Slot { get; set; }
}
主要問題在於,不清楚您在GetArmor
中要求什么。
返回值表明它應該恰好返回一個ArmorModel。 但是,您的查詢會生成一個列表,您嘗試將其返回。 當然這不會編譯。
此外,即使在您進行編輯后,EquipmentModel和ArmorModel之間的關系仍不清楚。
在您的查詢中,變量f的類型為EquipmentModel
而s的類型為ArmorModel
。 您在EquipmentModel.EquipmentId == ArmorModel.Id
上執行EquipmentModel.EquipmentId == ArmorModel.Id
。
似乎每個ArmorModel
都有零個或多個EquipmentModels
。 或用數據庫術語來說: ArmorModel
與EquipmentModel
之間ArmorModel
一對多關系,其中EquipmentModel
在屬性EquipmentId
ArmorModel
與其所屬的ArmorModel
的主鍵的外鍵。
除了在屬性命名中做出相當混亂的選擇之外,該一對多關系在您的類中沒有正確建模。 如果您希望實體框架表示一對多關系,那么類定義應類似於:
class ArmorModel
{
public int Id {get; set;}
// an ArmorModel has many EquipmentModels
public virtual ICollection>EquipmentModel> EquipmentModels {get; set;}
...
}
public class EquipmentModel
{
public int Id {get; set;}
// an EquipmentModel belongs to an ArmorModel via foreign key
public int EquipmentId {get; set;}
public virtual ArmorModel ArmorModel {get; set;}
...
}
public class MyDbContext : DbContext
{
public DbSet<EquipmentModel> EquipmentModels {get; set;}
public DbSet<ArmorModel> ArmorModels {get; set;}
}
由於表名/外鍵等之間不匹配,因此需要一些屬性或流暢的API。 考慮將屬性EquipmentId的名稱更改為適當的默認值ArmoreModelId。 實體框架將自動理解一對多關系:
public class EquipmentModel
{
public int Id {get; set;}
// an EquipmentModel belongs to an ArmorModel via proper default foreign key
public int ArmorModelId {get; set;}
public virtual ArmorModel ArmorModel {get; set;}
...
}
現在回到您的問題。 由於查詢和應返回的類型之間存在很大的不匹配,因此無法確定所需的內容。
如果看來你想要一個特殊ArmorModel
所有的集合ArmorModels
。 似乎您想要一個具有一個或多個與某些屬性匹配的EquipmentModels
的唯一ArmorModel
。
在正確的一對多定義之后,您的查詢將簡單得多:
var matchingArmoreModels = db.ArmorModels
// I don't want all ArmorModels,
// I only want those ArmorModels that have at least one EquipmentModel
// that match certain conditions with AccountId and EquipmentType
.Where(armorModel => armorModel.EquipmentModels
.Where(equipmentModel => equipmentModel.AccountId == user.Id
&& equipmentModel.EquipmentType == ...)
// it is enough if it has at least one matching EquipmentModel:
.Any());
現在你把所有ArmorModels
有至少一個EquipmentModel
用正確AccountId
和EquipmentType
。
當且僅當您確定應該有一個元素時,才可以返回Single
:
ArmorModel myOneAndOnlyArmorModel = matchingArmorModels.Single();
return myOneAndOnlyArmorModel;
如果您認為可能沒有匹配的ArmorModel
,請使用SingleOrDefault
。 如果您認為可能有多個匹配的ArmorModels
返回您的完整序列,或者返回第一個匹配的序列: FirstOrDefault
。
最后:可能是EquipmentModel不完全屬於一個ArmorModel,但可以屬於幾個ArmorModel。 在那種情況下,一對多關系是多對多關系,在此進行描述 。
在Fluent API中配置一對多
如果您使用實體框架代碼優先約定 ,則不必顯式定義一對多關系。 實體框架將自動檢測。
但是,如果要為外鍵或導航屬性使用非標准名稱,例如與在EquipmentModel中使用外鍵一樣,則必須幫助實體框架。
在重寫DbContext.OnModelCreating
最容易描述這DbContext.OnModelCreating
使用外鍵EquipmentId,每個EquipmentModel都完全屬於一個ArmorModel。 每個ArmorModel在屬性中都有許多EquipmentModels EquipmentModels
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EquipmentModel>()
.HasRequired(equipmentModel => equipmentModel.ArmorModel)
.WithMany(armorModel => armorModel.EquipmentModels)
.HasForeignKey(equipmentModel => equipmentModel.EquipmentId);
}
或者,您可以類似地配置ArmorModel:ArmorModel具有許多EquipmentModels。 使用外鍵EquipmentId,每個EquipmentModel都完全屬於一個ArmorModel。
modelBuilder.Entity<ArmorModel>()
.HasMany(armorModel => armorModel.EquipmentModels)
.WithRequired(equipmentModel => equipmentModel.ArmorModel)
.HasForeignKey(equipmentModel => EquipmentId);
確保不要同時指定兩者。 畢竟:只有一對多的關系
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.