【发布时间】:2013-06-25 00:13:21
【问题描述】:
我在 .net 4.5 控制台应用程序中使用 Entity Framework 5.0.0.0,我必须访问一个数据库,其中包含两个表,它们之间存在外键关系,如下所示:
奇怪的是外键在B(Almost1, Almost2) 和A(Almost1, Almost2) 之间,而不是从B(AId) 到A(AId)。 SQL 服务器允许这样做,因为 Almost1 和 Almost2 组合是唯一的,并且都不能为空(至少在表 A 上 - 在 B 上它们是可选的关系,但这是通过)。
这里有一些用于创建这种情况的 SQL:
CREATE TABLE [dbo].[A](
[AId] [int] IDENTITY(1,1) NOT NULL,
[Almost1] [int] NOT NULL,
[Almost2] [int] NOT NULL,
CONSTRAINT [PK_A] PRIMARY KEY CLUSTERED
(
[AId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [A_Constraint] UNIQUE NONCLUSTERED
(
[Almost1] ASC,
[Almost2] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[B](
[BId] [int] IDENTITY(1,1) NOT NULL,
[Almost1] [int] NULL,
[Almost2] [int] NULL,
CONSTRAINT [PK_B] PRIMARY KEY CLUSTERED
(
[BId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[B] ADD CONSTRAINT [FK_A_B] FOREIGN KEY([Almost1], [Almost2])
REFERENCES [dbo].[A] ([Almost1], [Almost2])
问题是,Entity Framework 似乎不允许这样做 - 是这种情况还是我没有正确定义我的模型?
这是我的 C#:
public class MyContext : DbContext
{
public MyContext(string connectionString) : base(connectionString)
{
MyAs = Set<A>();
MyBs = Set<B>();
}
public DbSet<A> MyAs { get; private set; }
public DbSet<B> MyBs { get; private set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var aEntity = modelBuilder.Entity<A>();
aEntity.ToTable("A");
aEntity.HasKey(a => a.AId);
var bEntity = modelBuilder.Entity<B>();
bEntity.ToTable("B");
bEntity.HasKey(a => a.BId);
bEntity
.HasOptional(b => b.A)
.WithMany(a => a.Bs)
.Map(m => m.MapKey("Almost1", "Almost2"));
}
}
public class A
{
public int AId { get; set; }
public int Almost1 { get; set; }
public int Almost2 { get; set; }
public virtual ICollection<B> Bs { get; private set; }
public void AddB(B b)
{
if (b == null) throw new ArgumentNullException("b");
if (Bs == null) Bs = new List<B>();
if (!Bs.Contains(b)) Bs.Add(b);
b.A = this;
}
}
public class B
{
public int BId { get; set; }
public virtual A A { get; set; }
}
class Program
{
static void Main()
{
using (var ctx = new MyContext(@"connection string"))
{
ctx.MyAs.Add(new A { Almost1 = 1, Almost2 = 1 });
ctx.SaveChanges();
}
}
}
它会抛出一个InvalidOperationException 说:
指定的关联外键列“Almost1,Almost2”无效。指定的列数必须与主键列数匹配。
如果我忽略AId 列,而是将Almost1 和Almost2 设为复合主键,那么我的OnModelCreating 方法现在看起来像这样:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var aEntity = modelBuilder.Entity<A>();
aEntity.ToTable("A");
aEntity.HasKey(a => new { a.Almost1, a.Almost2 });
aEntity.Ignore(a => a.AId);
var bEntity = modelBuilder.Entity<B>();
bEntity.ToTable("B");
bEntity.HasKey(a => a.BId);
bEntity
.HasOptional(b => b.A)
.WithMany(a => a.Bs)
.Map(m => m.MapKey("Almost1", "Almost2"));
}
它有效,但我真的不想这样做,因为还有一个表(我们称之为C)以传统方式与A 相关,具有AId 列和外部密钥从C.AId 变为A.AId。
是的,我知道这有点奇怪 - 但是可以在实体框架中处理这个问题吗?
【问题讨论】:
-
Entity Framework 不支持唯一键,如果没有这些,它就无法为您的外键建模,很遗憾。
标签: c# .net entity-framework-5 poco