首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EF Code First可选导航

EF Code First可选导航
EN

Stack Overflow用户
提问于 2011-12-13 06:01:24
回答 4查看 423关注 0票数 2

我有以下POCO对象:

代码语言:javascript
复制
public class Chat
{
    public int ChatID { get; set; }
    public virtual Audio ChatAudio { get; set; }
    public virtual Video ChatVideo { get; set; }
}

public class Audio
{
    public int AudioID { get; set; }
    public int ChatID { get; set; }
    public Chat Chat { get; set; }
    public DateTime Recorded { get; set; }
}

public class Video
{
    public int VideoID { get; set; }
    public int ChatID { get; set; }
    public Chat Chat { get; set; }
    public DateTime Recorded { get; set; }
}

DBA设置了以下表

代码语言:javascript
复制
-Chat-
ChatID

-Audio-
AudioID
ChatID <-- FK, Unique Index
Recorded

-Video-
VideoID
ChatID <-- FK, Unique Index
Recorded

所以这是一个1对可选的关系。他不想在Chat表上为Audio或Video创建一个可以为空的列。如何在EF代码中强制执行此操作?我让它工作的唯一方法是创建那些导航属性集合和定义的HasMany()。我不想那样做。我希望能够做到:

代码语言:javascript
复制
if(Chat.Audio == null || Chat.Video==null)
{
// Do stuff
}

我很感谢你的任何建议。

EN

回答 4

Stack Overflow用户

发布于 2011-12-13 07:07:04

不能,您不能使用Entity Framework将此模型映射到您的数据库架构(无论是哪个版本到当前版本4.2)。

主要原因是EF不支持唯一键约束,这意味着:将引用导航属性映射到数据库中具有唯一键约束的列。EF会认为数据库中这样的FK列始终不是唯一的,并且看不到唯一键约束。因此,Chat中两个关联的结尾必须是集合。或者你不能在你的模型中公开它们,但是在内部EF会一直认为它们是“许多”-ends。

EF支持的唯一真正的一对一关系是共享主键关系。这意味着在AudioVideo表中没有ChatId列,而是主键列AudioIdVideoId同时是Chat表的外键列。显然,主键列不可能是数据库中所有自动生成的标识,从而使这种映射成为可能。

在这里可以找到对一对一映射策略的很好的描述以及它们的优点和限制的比较:

  • Shared Primary Key Associations
  • One-to-One Foreign Key Associations
票数 2
EN

Stack Overflow用户

发布于 2011-12-14 02:17:07

您可以“作弊”并将关系配置为一对多,在对象模型中强制执行一对一(此外,在datacontext初始化器中,您可以手动向数据库添加唯一约束)。

它基本上看起来像这样

代码语言:javascript
复制
public class Chat 
{ 
    public int ChatID { get; set; } 
    protected virtual ICollection<Audio> HiddenAudioCollection{get;set;}
    public Audio ChatAudio 
    { 
      get{return HiddenAudioCollection.FirstOrDefault();} 
      set
      {
        if(HiddenAudioCollection==null)
          HiddenAudioCollection=new List<Audio>();
        if(HiddenAudioCollection.Any())
        {
          //decide if you throw an exception or delete the existing Audio
        }

        HiddenAudioCollection.Add(value);
      } 
    } 
    //Do the same with ChatVideo
} 
票数 0
EN

Stack Overflow用户

发布于 2011-12-14 02:39:26

让我确认一下我的理解是否正确:

聊天有零个或一个音频,零个或一个视频。

音频,如果存在,恰好属于1个聊天。视频,如果它存在,恰好属于1个聊天。

这是正确的吗?如果是这样,您的DBA会介意这样的模式吗?

代码语言:javascript
复制
-Chat-
ChatID

-Audio-
ChatID <-- FK, Primary Key
Recorded

-Video-
ChatID <-- FK, Primary Key
Recorded

如果是这样,我认为你可以这样做:

代码语言:javascript
复制
public class Chat
{
    public int ChatID { get; set; }
    public virtual Audio ChatAudio { get; set; }
    public virtual Video ChatVideo { get; set; }
}

public class Audio
{
    public int ChatID { get; set; }
    public virtual Chat Chat { get; set; }
    public DateTime Recorded { get; set; }
}

public class Video
{
    public int ChatID { get; set; }
    public virtual Chat Chat { get; set; }
    public DateTime Recorded { get; set; }
}

..。

代码语言:javascript
复制
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Audio>().HasKey(a => a.ChatID);
    modelBuilder.Entity<Video>().HasKey(a => a.ChatID);
    var chat = modelBuilder.Entity<Chat>();
    chat
        .HasOptional(c => c.ChatAudio)
        .WithRequired(a => a.Chat);

    chat
        .HasOptional(c => c.ChatVideo)
        .WithRequired(a => a.Chat);
    ...
 }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8481497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档