Ral*_*ton 16 entity-framework code-first
当使用实体框架代码优先库的CTP 5(如宣布在这里)我试图创建一个映射到一个非常简单的层次结构表中的类.
这是构建表的SQL:
CREATE TABLE [dbo].[People]
(
Id uniqueidentifier not null primary key rowguidcol,
Name nvarchar(50) not null,
Parent uniqueidentifier null
)
ALTER TABLE [dbo].[People]
ADD CONSTRAINT [ParentOfPerson]
FOREIGN KEY (Parent)
REFERENCES People (Id)
Run Code Online (Sandbox Code Playgroud)
这是我希望自动映射回该表的代码:
class Person
{
public Guid Id { get; set; }
public String Name { get; set; }
public virtual Person Parent { get; set; }
public virtual ICollection<Person> Children { get; set; }
}
class FamilyContext : DbContext
{
public DbSet<Person> People { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我在app.config文件中设置了connectionstring,如下所示:
<configuration>
<connectionStrings>
<add name="FamilyContext" connectionString="server=(local); database=CodeFirstTrial; trusted_connection=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
Run Code Online (Sandbox Code Playgroud)
最后我试图使用类添加父和子实体,如下所示:
static void Main(string[] args)
{
using (FamilyContext context = new FamilyContext())
{
var fred = new Person
{
Id = Guid.NewGuid(),
Name = "Fred"
};
var pebbles = new Person
{
Id = Guid.NewGuid(),
Name = "Pebbles",
Parent = fred
};
context.People.Add(fred);
var rowCount = context.SaveChanges();
Console.WriteLine("rows added: {0}", rowCount);
var population = from p in context.People select new { p.Name };
foreach (var person in population)
Console.WriteLine(person);
}
}
Run Code Online (Sandbox Code Playgroud)
这里显然缺少一些东西.我得到的例外是:
列名称'PersonId'无效.
我理解约定对配置的价值,我和我的团队对放弃edmx /设计师噩梦的前景感到非常兴奋 - 但似乎没有关于约定的明确文件.(我们只是幸运地参与了多个表名的概念,对于单数类名)
关于如何使这个非常简单的例子落实到位的一些指导将不胜感激.
更新:将People表中的列名从Parent更改为PersonId允许Add fred
to继续.Howerver你会注意到这pebbles
是一个添加到Children系列中的fred
,因此我希望在添加Fred时将鹅卵石添加到数据库中,但事实并非如此.这是一个非常简单的模型,所以我有点沮丧的是,在将几行输入数据库时应该有这么多的猜测工作.
Mor*_*avi 14
您需要下拉到流畅的API以实现所需的架构(数据注释不会这样做).确切地说,您还有一个Independent One-to-Many Self Reference Association
外键列(People.Parent)的自定义名称.以下是如何使用EF Code First完成的:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children)
.IsIndependent()
.Map(m => m.MapKey(p => p.Id, "ParentID"));
}
Run Code Online (Sandbox Code Playgroud)
但是,这会抛出一条InvalidOperationException
带有此消息的Sequence包含多个匹配元素.根据Steven在他的回答中提到的链接,这听起来像是一个CTP5错误.
您可以使用解决方法,直到在RTM中修复此错误,并接受FK列的默认名称PersonID
.为此,您需要稍微更改架构:
CREATE TABLE [dbo].[People]
(
Id uniqueidentifier not null primary key rowguidcol,
Name nvarchar(50) not null,
PersonId uniqueidentifier null
)
ALTER TABLE [dbo].[People] ADD CONSTRAINT [ParentOfPerson]
FOREIGN KEY (PersonId) REFERENCES People (Id)
GO
ALTER TABLE [dbo].[People] CHECK CONSTRAINT [ParentOfPerson]
GO
Run Code Online (Sandbox Code Playgroud)
然后使用这个流畅的API将您的数据模型与DB Schema匹配:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children)
.IsIndependent();
}
Run Code Online (Sandbox Code Playgroud)
using (FamilyContext context = new FamilyContext())
{
var pebbles = new Person
{
Id = Guid.NewGuid(),
Name = "Pebbles",
};
var fred = new Person
{
Id = Guid.NewGuid(),
Name = "Fred",
Children = new List<Person>()
{
pebbles
}
};
context.People.Add(fred);
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
using (FamilyContext context = new FamilyContext())
{
var fred = new Person
{
Id = Guid.NewGuid(),
Name = "Fred",
};
var pebbles = new Person
{
Id = Guid.NewGuid(),
Name = "Pebbles",
Parent = fred
};
context.People.Add(pebbles);
var rowCount = context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
这两个代码具有相同的效果,即添加带有子项(Pebbles)的新父(Fred).
归档时间: |
|
查看次数: |
18994 次 |
最近记录: |