联接两个列表返回 IEnumerable C# 实体框架中的 IEnumerable



我试图加入两个列表,但是当我只期望简单的列表时,结果给了我一个IEnumerable中的IEnumerable。我可以将两个 IEnumerable 都投射到列表中,但我首先对为什么会发生这种情况感到困惑。为什么会这样,我需要做什么才能从联接中仅获取一个列表?

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中要求什么。

返回值表示它应该只返回一个装甲模型。然而,您的查询会产生一个您尝试返回的列表。当然这不会编译。

此外,即使在您编辑之后,装备模型和装甲模型之间的关系也不清楚。

在查询中,变量 f 的类型为EquipmentModel,s 的类型为ArmorModel。在EquipmentModel.EquipmentId == ArmorModel.Id上执行联接。

似乎每个ArmorModel都有零个或多个EquipmentModels.或者在数据库术语中:ArmorModelEquipmentModel之间存在一对多关系,其中EquipmentModel在属性EquipmentId中具有它所属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;}
...
}

现在回到你的问题。由于查询与应返回的类型之间存在如此大的不匹配,因此无法确定所需的内容。

如果您似乎想要从所有ArmorModels集合中获取一个特殊ArmorModel。您似乎想要具有一个或多个与某些属性匹配的EquipmentModels的 one-onlyArmorModel

在正确的一对多定义之后,您的查询将简单得多:

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());

现在,您拥有至少具有一个具有正确AccountIdEquipmentTypeEquipmentModel的所有ArmorModels

当且仅当您确定应该有一个元素时,您可以返回Single

ArmorModel myOneAndOnlyArmorModel = matchingArmorModels.Single();
return myOneAndOnlyArmorModel;

如果您认为可能没有匹配的ArmorModel,请使用SingleOrDefault。如果您认为可能有多个匹配ArmorModels返回完整的序列,或返回第一个匹配的序列:FirstOrDefault.

最后:一个装备模型可能不完全属于一个装甲模型,但它可以属于多个装甲模型。在这种情况下,一对多关系是多对多关系,此处对此进行了描述。

在 Fluent API 中配置一对多

如果使用实体框架代码优先约定,则不必显式定义一对多关系。实体框架将自动检测。

但是,如果要为外键或导航属性使用非标准名称,就像在 EquipmentModel 中使用外键一样,则必须帮助实体框架。

在覆盖DbContext.OnModelCreating时最容易描述这一点

每个装备模型只属于一个装甲模型,使用外键装备ID。每个装甲模型都有许多装备属性中的装备模型装备模型

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EquipmentModel>()
.HasRequired(equipmentModel => equipmentModel.ArmorModel)
.WithMany(armorModel => armorModel.EquipmentModels)
.HasForeignKey(equipmentModel => equipmentModel.EquipmentId);
}

或者,您可以类似地配置装甲模型:装甲模型有许多装备模型。每个装备模型只属于一个装甲模型,使用外键装备ID。

modelBuilder.Entity<ArmorModel>()
.HasMany(armorModel => armorModel.EquipmentModels)
.WithRequired(equipmentModel => equipmentModel.ArmorModel)
.HasForeignKey(equipmentModel => EquipmentId);

请确保不要同时指定两者。毕竟:只有一个一对多关系

最新更新