惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
Recent Announcements
Recent Announcements
IT之家
IT之家
人人都是产品经理
人人都是产品经理
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
大猫的无限游戏
大猫的无限游戏
U
Unit 42
罗磊的独立博客
博客园 - Franky
WordPress大学
WordPress大学
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
SecWiki News
SecWiki News
V
Vulnerabilities – Threatpost
P
Privacy International News Feed
P
Palo Alto Networks Blog
F
Fortinet All Blogs
P
Proofpoint News Feed
博客园 - 叶小钗
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
Spread Privacy
Spread Privacy
S
Securelist
C
Cisco Blogs
I
Intezer
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cyberwarzone
Cyberwarzone
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
GbyAI
GbyAI
T
Troy Hunt's Blog
T
Threatpost
博客园 - 司徒正美
Y
Y Combinator Blog
Hugging Face - Blog
Hugging Face - Blog
AWS News Blog
AWS News Blog
T
The Blog of Author Tim Ferriss
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
酷 壳 – CoolShell
酷 壳 – CoolShell
Google DeepMind News
Google DeepMind News
Know Your Adversary
Know Your Adversary
S
SegmentFault 最新的问题

博客园 - 阿修

让Entity Framework启动不再效验__MigrationHistory表 Entity Framework搜索指定字段解决方案 Linux+Mono+WebService:CS1703: An assembly with the same identity--mscorlib 获取某年中第几个礼拜的第一天的函数 DataTable.Rows.Remove(row) 与 DataTable.Rows[i].Delete()区别 [转摘]Lucene学习总结之一:全文检索的基本原理 Lucene.net根据Sort走到了不同的类处理 VPN Connections and Default Gateways - 阿修 牛!帮EXE等执行文件压缩的工具 进程通讯的多种方式 三星I9008删除程序清单 .NET编程中的部分效率问题 质量保证漫漫谈之QA、QC、QM的关系与区别 敏捷宣言 多维角度聊聊结对编程 在Windows下编译和.NET运行MemCached Serv-U服务器中文乱码问题的解决 请小心 管理学中四件不要做的事情
Entity FrameWork 单表对多实体
阿修 · 2013-08-19 · via 博客园 - 阿修

一个影片信息Clips表,四个字段:clipId,clipName,fileSize,fileName

方案一:

    [Table("Clips")]
    public class Clip
    {
        public Clip()
        {
            File = new ClipFile();
        }

        [Key]
        [Column("clipId")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Column("clipName")]
        public string Name { get; set; }

        public ClipFile File { get; set; }
    }

    [ComplexType]
    public class ClipFile
    {
        [Column("fileSize")]
        public string Size { get; set; }

        [Column("fileName")]
        public string Name { get; set; }
    }

缺点:ClipFile不会延迟加载,无论你ClipFile申明是否为virtual的。

方案二:

[Table("Clips")]
    public class Clip
    {
        [Key]
        [Column("clipId")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [ForeignKey("FileOf")]
        public int Id { get; set; }

        [Column("clipName")]
        public string Name { get; set; }

        //[Required]
        public virtual ClipFile FileOf { get; set; }
    }

    [Table("Clips")]
    public class ClipFile
    {
        [Key]
        [Column("clipId")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [ForeignKey("ClipOf")]
        public int Id { get; set; }

        [Column("fileSize")]
        public string Size { get; set; }

        [Column("fileName")]
        public string Name { get; set; }
        
        //[Required]
        public virtual Clip ClipOf { get; set; }
    }

这种方案也存在问题,不Include调用关联virtual实体类,永远是null,不支持延迟加载,很是郁闷。SqlServer据说可以解决,MySql我是没有找到解决方案。

还有就是构造函数一定不要去new附属实体类,会进入死循环。

方案三:使用TPH(Table per Hierarchy)

public abstract class ClipBase
    {
        [Key]
        [Column("clipId")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Column("clipName")]
        public string Name { get; set; }
    }

    public class ClipFile : ClipBase
    {
        [Column("fileName")]
        public string FileName { get; set; }
    }

    public class ClipSize : ClipBase
    {
        [Column("fileSize")]
        public int Size { get; set; }
    }

而且必须是用Fluent API进行配置,还必须为Clips添加字段Discriminator(字段名称和类型都可以根据自己需要进行修改),这个字段的值用于区分是哪个类的数据,所以务必保证每个派生类的HasValue值不相同。

modelBuilder.Entity<ClipBase>().Map(m=>
            {
                m.ToTable("Clips");
                //m.Requires("Discriminator").HasValue("0"); //如果ClipBase不申明为抽象类这需要用此加以区分
            })
            .Map<ClipFile>(m => m.Requires("Discriminator").HasValue("1"))
            .Map<ClipSize>(m => m.Requires("Discriminator").HasValue("2"));

创建对象可以用基类的DbSet进行添加,也可以用派生类自己的DbSet进行添加。选取的时候你可以基类的DbSet.OfType<ClipFile>(),也可以用派生类自己的DbSet。

但是这种方案多实体其实就导致数据虽然在一个表,但是内容无法在三个类中共享了,失去了原有的设计初衷。