首页 新闻 会员 周边 捐助

EF Core 2.2使用Code First模式如何设置主键不自增(如何设置主键可赋值)

0
悬赏园豆:10 [已解决问题] 解决于 2019-01-31 14:34

【环境】:.NET Core 2.2 + EF Core 2.2,使用Code First模式,实体Entity的映射没有写在Entity里,分离了出来单独配置,通过实现IEntityTypeConfiguration接口来实现映射的,具体代码如下:

实体类(EntityBase):

/// <summary>实体基类</summary>
public class EntityBase
{
    /// <summary>主键</summary>
    /// <value>The identifier.</value>
    public long Id { get; set; }
    /// <summary>创建人姓名</summary>
    /// <value>The name of the create.</value>
    public string CreateName { get; set; } = string.Empty;
    /// <summary>创建人Id</summary>
    /// <value>The create identifier.</value>
    public long? CreateId { get; set; }
    /// <summary>创建时间</summary>
    /// <value>The create time.</value>
    public DateTime? CreateTime { get; set; }
    /// <summary>更新人姓名</summary>
    /// <value>The name of the update.</value>
    public string UpdateName { get; set; } = string.Empty;
    /// <summary>更新人Id</summary>
    /// <value>The update identifier.</value>
    public long? UpdateId { get; set; }
    /// <summary>更新时间</summary>
    /// <value>The update time.</value>
    public DateTime? UpdateTime { get; set; }
    /// <summary>数据状态</summary>
    /// <value>The state of the data.</value>
    public bool IsDeleted { get; set; }
    /// <summary>基础字段设置方法</summary>
    /// <value>The automatic setter.</value>
    public IEntityBaseAutoSetter AutoSetter { get; set; }
}

映射类:

/// <summary>Map实体基类的基础字段</summary>
/// <typeparam name="T"></typeparam>
public abstract class EntityBaseTypeConfig<T> : IEntityTypeConfiguration<T> where T : EntityBase
{
    public virtual void Configure(EntityTypeBuilder<T> builder)
    {
        builder.HasKey(it => it.Id);
        builder.Property(x => x.CreateId).IsRequired(false);
        builder.Property(x => x.CreateName).HasMaxLength(128).IsRequired(false);
        builder.Property(x => x.CreateTime).IsRequired(false);
        builder.Property(x => x.UpdateId).IsRequired(false);
        builder.Property(x => x.UpdateName).HasMaxLength(128).IsRequired(false);
        builder.Property(x => x.UpdateTime).IsRequired(false);
        builder.Property(x => x.IsDeleted).IsRequired();
        builder.Ignore(x => x.AutoSetter);
    }
}

【问题】
其中Id设置了主键,在Code First生成数据库时,主键自动设置了自增长,但是框架在向表添加数据时会生成Guid赋值给主键Id,导致保存到数据库是报错,报错内容如下:

[ System.Data.SqlClient.SqlException (0x80131904): 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'Student' 中的标识列插入显式值。]

【期望】
映射的时候,如何设置主键不增长,或者说如何设置主键可赋值?
框架可以使用自己的规则生成Id作为主键存入数据库。

【补充】
在EF 6.x的版本中,可以通过继承EntityTypeConfiguration类,然后设置如下方式实现
this.Property<long>((Expression<Func<T, long>>) (x => x.Id)).IsRequired().HasDatabaseGeneratedOption(new DatabaseGeneratedOption?(DatabaseGeneratedOption.None));
但是在EF Core中我好像没有找到类似的方法

在7楼的主页 在7楼 | 初学一级 | 园豆:151
提问于:2019-01-30 18:12
< >
分享
最佳答案
0

试试 builder.Property(x => x.Id).ValueGeneratedNever();

收获园豆:10
dudu | 高人七级 |园豆:31053 | 2019-01-30 18:33

感谢,已解决。
但是同时又发现了新的问题:在修改主键字段属性的时候,EF Core会报错【更改列的IDENTITY属性,需要删除并重新创建列】,只能删掉再重新创建。
搜索后发现,在EF Core的源码下已经有人提过issue了(https://github.com/aspnet/EntityFrameworkCore/issues/7444)。
这是EF Core当前版本还没有解决的Bug?

在7楼 | 园豆:151 (初学一级) | 2019-01-31 12:50

@在7楼: 为什么不直接在数据库中修改?

dudu | 园豆:31053 (高人七级) | 2019-01-31 13:12

@dudu: 没有针对这个问题和解决方案,主要是好奇这个是属于EF Core遗留的未解决Bug,还是以后版本也不打算解决(设计就是一旦Code First初始化主键之后就不可以修改主键属性了)?

在7楼 | 园豆:151 (初学一级) | 2019-01-31 13:19

@在7楼: 等 EF Core 3.0

dudu | 园豆:31053 (高人七级) | 2019-01-31 13:32
其他回答(1)
0

这是设计思维的理解不一样, 主键是一个对象标识自身不同于其它对象的方式。

如果修改主键,那么就有可能把主键的值修改成与其它对象的主键相同,那么主键本身的【唯一性】功能就尚是了,接下来还会引发更严重的事情,造成一个表中存在相同主键的多个对象。

—— 当然题主肯定是不会做这种操作的,但从编程的绝对可靠原则上,为了避免此类事件发生,所以不允许修改主键,个人观点。

develope-logs | 园豆:204 (菜鸟二级) | 2019-02-01 17:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册