zoukankan      html  css  js  c++  java
  • Entity Framework 小知识分享

    与Entity Framework相伴的日子痛并快乐着。今天和大家分享一下一个快乐,两个痛苦。

    先说快乐的吧。Entity Framework在将数据插入数据库时,如果主键字段是自增标识列,会将该自增值返回给实体对象对应的属性。

    比如下面添加博客随笔至数据库的示例代码:

    var blogPost = new BlogPost()
    {
    Author
    = "博客园",
    Title
    = "程序员的网上家园"
    };
    using (BlogDbContext context = new BlogDbContext())
    {
    context.BlogPosts.Add(blogPost);
    context.SaveChanges();
    return blogPost.ID;
    }

    SaveChanges()之后,blogPost.ID的值就是数据库中对应自增标识列的值。

    看一下Entity Framework生成的SQL语句:

    exec sp_executesql N'insert [dbo].[blog_Content]([Title],[Author])
    values (@0, @1)
    select [ID]
    from [dbo].[blog_Content]
    where @@ROWCOUNT > 0 and [ID] = scope_identity()
    ',
    N
    '@0 nvarchar(128),@1 nvarchar(128),',@0=N'程序员的网上家园',@1=N'博客园'

    EF通过scope_identity()获取自增列的值,而且我们没有对BlogPost的ID属性进行任何设置,是EF智能地判断出ID就是自增标识列。

    在以前没有使用Entity Framework的时代,用的是存储过程,存储过程有一堆参数,实体对象的属性值要一一对应地赋值给这些参数,执行存储过程之后,还要通过ParameterDirection.Output的参数获取自增ID的值。

    现在,只要把东西交给Entity Framework,并和她说,把它放到数据库中去。多省心!多快乐!

    但是,自以为是的Entity Framework用这个特性给人快乐的同时,也给人带来了一点痛苦。她认为只要实体类中有ID属性,数据库对应的是一定是自增标识列,真是够自以为是的。当我们把博客随笔添加至数据库后,准备用这个自增ID将随笔内容添加至数据库(随笔内容存储在单独的数据库,通过ID字段与随笔进行关联,不是自增的),却出现错误提示:

    Cannot insert the value NULL into column 'ID', 
    table 'CNBlogsText.dbo.blog_PostBody'; column does not allow nulls.

    看看EF生成的SQL语句:

    exec sp_executesql N'insert [dbo].[CNBlogsText_blog_PostBody]([Text])
    values (@0)
    select [ID]
    from [dbo].[CNBlogsText_blog_PostBody]
    where @@ROWCOUNT > 0 and [ID] = scope_identity()
    ',N'@0 nvarchar(128)',@0=N'帮助程序员用技术改变世界'

    不是自增列,也来个scope_identity()。这么聪明的Entity Framework,也会干这样的傻事。

    还好,EF定制灵活的特性可以让我们轻松化解这个痛苦,只要在BlogDbContext中添加下面的代码:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    modelBuilder.Entity
    <PostBody>().Property(p => p.ID)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }

    也可以通过在实体类属性上加标记实现:

    public class BlogPost
    {
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ID { get; set; }
    }
    第二个痛苦是众所周知的Entity Framework不支持枚举类型,虽然大家都知道,但还是想拿出晒晒,解解恨。

    EF怎么对待枚举类型的呢?对于实体类中实实在在存在的枚举类型的属性,EF对它们视而不见,就当它不存在。

    对于这个痛苦,目前无法化解(要等EF的下一版本),只能借助旁边左道减轻痛苦,请看“旁边左道”之“移花接木”。

    实体类中的代码:

    public class BlogPost
    {
    public BlogPostType PostType
    {
    get { return (BlogPostType)PostTypeEf; }
    set { PostTypeEf = (int)value; }
    }
    public int PostTypeEf { get; set; }
    }

    EF不认枚举类型,但认int类型,所以增加个PostTypeEf,仅供EF专用,等EF的下一版本支持枚举类型时再去掉。

    BlogDbContext也要配合着进行修改:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    modelBuilder.Entity
    <BlogPost>().Ignore(p => p.PostConfig);
    modelBuilder.Entity
    <BlogPost>().Property(p => p.PostTypeEf)
    .HasColumnName(
    "PostType");
    }
    分享完毕,快乐更加快乐,痛苦不再痛苦。
  • 相关阅读:
    ffmpeg文档22-混合器(复用器)
    ffmpeg文档21-分离器
    ffmpeg文档20-格式选项
    ffmpeg文档19-比特流滤镜
    ffmpeg文档18-字幕编码器
    ffmpeg文档17-视频编码器
    ffmpeg文档16-音频编码器
    python 学习笔记,selenium 自动化测试 更新开始
    python 遇到 'unicode' object is not callable 错误
    字符串函数汇总
  • 原文地址:https://www.cnblogs.com/dudu/p/entity_framework_tips_1.html
Copyright © 2011-2022 走看看