问: 当我尝试从
_Db
返回数据时,我在 List
属性中得到空对象,我想知道为什么其他属性能够正确返回,而 List
却没有?
问题解释:我有
ApplicationDbContext
类
public IDbSet<Player> Players { get; set; }
属性。具有以下 ApplicationDbInitializer
类:
public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
context.Players.Add(new Player { PlayerName = "john", PlayerSkills = new List<string> { "a", "b" } });
context.Players.Add(new Player { PlayerName = "Wuli", PlayerSkills = new List<string> { "c", "d" } });
base.Seed(context);
}
}
我的
Player
课程看起来像这样:
public class Player
{
[Key]
public int Id { get; set; }
public string PlayerName { get; set; }
public List<string> PlayerSkills { get; set; }
}
我对数据的请求如下所示:
public IEnumerable<Player> Get()
{
return _Db.Players;
}
它绝对正确地返回
Id
和 PlayerName
,但对于 null
列表返回 PlayerSkills
。
_Db
正在与 Controller
相同的 Get()
类中按以下方式初始化:
ApplicationDbContext _Db = new ApplicationDbContext();
SQL中有一种字段类型可以存储值的集合。如果您查看 EF 生成的表,您将不会看到其中归档的
PlayerSkills
。创建脚本看起来像
CREATE TABLE [dbo].[Players] (
[Id] [int] NOT NULL IDENTITY,
[PlayerName] [nvarchar](max),
CONSTRAINT [PK_dbo.Players] PRIMARY KEY ([Id])
)
这就是为什么您在
PlayerSkills
字段中没有获得任何数据的原因。如果您想在 SQL 数据库中存储一对多关系,您需要第二个表来存储玩家技能以及与这些技能相关的玩家 ID。如果您想避免技能重复,甚至可以使用两张表 - 一张用于技能,一张用于将玩家映射到技能的连接表。
没有联结表(如果您不希望外键具有显式属性,那么您的选择是流畅映射而不是属性映射):
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>()
.HasMany(p => p.PlayerSkills).WithRequired();
base.OnModelCreating(modelBuilder);
}
玩家技能
public class PlayerSkill
{
public int Id { get; set; }
public string Name { get; set; }
}
玩家
public class Player
{
public int Id { get; set; }
public string PlayerName { get; set; }
public virtual List<PlayerSkill> PlayerSkills { get; set; }
}
带接线台
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>()
.HasMany(p => p.PlayerSkills)
.WithMany()
.Map(j => j.MapLeftKey("PlayerId")
.MapRightKey("PlayerSkillId")
.ToTable("PlayerToSkill"));
base.OnModelCreating(modelBuilder);
}
当您想从 ICollection 数据库访问属性时,您需要像下面这样包含它:
public IEnumerable<Player> Get()
{
return _Db.Players.Include(p => p.PlayerSkills );
}
这样,PlayerSkills 字段就不再为空了。