Entity Framework添加记录时获取自增ID值

与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也要
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中整合MongoDB实现自增ID可以通过自定义序列来实现。以下是一种常见的实现方式: 1. 首先,创建一个名为Sequence的实体类,用于保存自增ID的当前: ```java package com.example.entity; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document(collection = "sequences") public class Sequence { @Id private String id; private long value; public String getId() { return id; } public void setId(String id) { this.id = id; } public long getValue() { return value; } public void setValue(long value) { this.value = value; } } ``` 2. 接下来,创建一个名为SequenceGenerator的自定义序列生成器类,用于生成自增ID: ```java package com.example.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.FindAndModifyOptions; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; import com.example.entity.Sequence; @Service public class SequenceGenerator { private final MongoOperations mongoOperations; @Autowired public SequenceGenerator(MongoOperations mongoOperations) { this.mongoOperations = mongoOperations; } public long generateSequence(String seqName) { Query query = new Query().addCriteria(Criteria.where("_id").is(seqName)); Update update = new Update().inc("value", 1); FindAndModifyOptions options = new FindAndModifyOptions().returnNew(true).upsert(true); Sequence sequence = mongoOperations.findAndModify(query, update, options, Sequence.class); return sequence.getValue(); } } ``` 3. 最后,在需要生成自增ID的实体类中使用@Autowired注入SequenceGenerator,并使用@PrePersist注解在保存实体之前生成自增ID: ```java package com.example.entity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PrePersist; import org.springframework.data.mongodb.core.mapping.Document; import com.example.service.SequenceGenerator; @Document(collection = "users") public class User { @Id private long id; private String name; private int age; @Autowired private SequenceGenerator sequenceGenerator; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @PrePersist public void generateId() { this.id = sequenceGenerator.generateSequence(User.SEQUENCE_NAME); } } ``` 通过以上方式,就可以在Spring Boot整合MongoDB中实现自增ID的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [springboot jpa id 自增问题解决](https://blog.csdn.net/helloexp/article/details/121474077)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值