簡體   English   中英

連接兩個列表在IEnumerable C#實體框架中返回IEnumerable

[英]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 或用數據庫術語來說: ArmorModelEquipmentModel之間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用正確AccountIdEquipmentType

當且僅當您確定應該有一個元素時,才可以返回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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM