我试图加入两个列表,但是当我期待只有简单的List时,结果在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; }
}
答案 0 :(得分:1)
主要问题是在GetArmor
中不清楚你要求的是什么。
返回值表示它应该只返回一个ArmorModel。然而,您的查询会生成您尝试返回的List。当然这不会编译。
此外,即使在编辑之后,EquipmentModel和ArmorModel之间的关系也不清楚。
在您的查询中,变量f的类型为EquipmentModel
,而s的类型为ArmorModel
。您在EquipmentModel.EquipmentId == ArmorModel.Id
上执行了加入。
似乎每个ArmorModel
都有零个或多个EquipmentModels
。或者在数据库术语中:ArmorModel
和EquipmentModel
之间存在一对多关系,其中EquipmentModel
具有其所属ArmorModel
主键的外键在财产EquipmentId
。
除了在属性命名中相当混乱的选择之外,这种一对多关系在您的类中没有正确建模。如果您希望实体框架代表您的一对多关系,那么类定义应该是:
See this article about proper one-to-many Entity Framework relations
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
。您似乎希望只有ArmorModel
一个或多个EquipmentModels
匹配某些属性。
在正确的一对多定义之后,您的查询会更简单:
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。在这种情况下,一对多关系是many-to-many relation, which is described here。
在Fluent API中配置一对多
如果您使用entity framework code first conventions,则无需明确定义一对多关系。实体框架将自动检测。
但是,如果要为外键或导航属性使用非标准名称,就像使用EquipmentModel中的外键一样,则必须帮助实体框架。
最简单的方法是在覆盖DbContext.OnModelCreating
每个EquipmentModel都属于一个ArmorModel,使用外键EquipmentId。每个ArmorModel都在属性EquipmentModels
中有许多EquipmentModelprotected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EquipmentModel>()
.HasRequired(equipmentModel => equipmentModel.ArmorModel)
.WithMany(armorModel => armorModel.EquipmentModels)
.HasForeignKey(equipmentModel => equipmentModel.EquipmentId);
}
或者你可以类似地配置ArmorModel:ArmorModel有许多EquipmentModelss。每个EquipmentModel都属于一个ArmorModel,使用外键EquipmentId。
modelBuilder.Entity<ArmorModel>()
.HasMany(armorModel => armorModel.EquipmentModels)
.WithRequired(equipmentModel => equipmentModel.ArmorModel)
.HasForeignKey(equipmentModel => EquipmentId);
请务必不要同时指定两者。毕竟:只有一对一的关系