2015-06-24 86 views
2

我需要在EF对象的多个属性上放置一个唯一的约束。这些属性之一是一个对象(导航属性)导航属性的唯一约束

public class foo 
{ 
    [Key] 
    public int FooID {get; set;} 
    <other properties here> 
} 
public class bar 
{ 
    [Key] 
    public int barID {get;set;} 
    [Index("IX_UniqueWithinFoo", 0, IsUnique = true)] 
    public virtual foo parent {get;set;} 
    [Index("IX_UniqueWithinFoo", 1, IsUnique = true)] 
    public int order {get; set;} 
} 

我无法找到任何文件,以确定这是否是正确的做法,尤其是插入foo对象将不能划上等号的时候,因为。

回答

1

用这种模型,EF创建以下表/索引/约束

CREATE TABLE [Bars] (
[barID] int not null identity(1,1) 
, [order] int not null 
, [parent_FooID] int null 
); 

ALTER TABLE [Bars] ADD CONSTRAINT [PK_Bars_8873614b] PRIMARY KEY ([barID]) 

CREATE TABLE [Foos] (
[FooID] int not null identity(1,1) 
); 

ALTER TABLE [Foos] ADD CONSTRAINT [PK_Foos_8873614b] PRIMARY KEY ([FooID]) 

CREATE UNIQUE INDEX [IX_UniqueWithinFoo] ON [Bars] ([order]) 

CREATE INDEX [IX_parent_FooID] ON [Bars] ([parent_FooID]) 

ALTER TABLE [Bars] ADD CONSTRAINT [FK_Bars_Foos_parent_FooID] FOREIGN KEY ([parent_FooID]) REFERENCES [Foos] ([FooID]) 

看第二个创建索引... EF完全无视索引名和唯一约束。我认为这可能被认为是一个错误。

如果你想解决这个问题,你需要在类Bar中为关系插入一个属性(至少如果你使用数据注解)并在其上设置唯一索引。

public class Bar 
{ 
    [Key]  
    public int barID {get;set;} 

    [Index("IX_UniqueWithinFoo", 0, IsUnique = true)] 
    public int parent_FooId { get; set; } 

    [ForeignKey("parent_FooId")] 
    public virtual Foo parent { get; set; } 

    [Index("IX_UniqueWithinFoo", 1, IsUnique = true)] 
    public int order { get; set; } 
} 

在这种情况下,只有创建一个指数,该指数是

CREATE UNIQUE INDEX [IX_UniqueWithinFoo] ON [Bars] ([parent_FooId], [order]) 
+0

所以在本质上说,解决这一问题的唯一途径是增加外键属性?我可以看到它是如何工作的,但看起来有点肮脏。我会在滴答作答之前看看是否有人有更清洁的解决方案,但谢谢你的答案! –

+1

还有其他两种方法。首先是创建索引与代码迁移(我真的不喜欢它)。第二种方法(不是真正的新方法,只是使解决方案稍微清晰一些)的方法是将parent_FooId属性设置为private,然后通过流畅接口(它必须是Bar内部的类)映射它。至少,Bar用户没有看到parent_FooId prop ... – bubi