首先使用代码禁用整数主键上的标识(自动递增)

时间:2011-08-26 14:33:53

标签: asp.net-mvc-3 entity-framework

我在ASP.NET MVC 3应用程序中使用代码优先方法,并且模型中的所有整数主键(public int Id { get; set; })默认配置为具有自动递增的标识。如何禁用它并启用一种手动输入主键整数的方法?

实际情况是Id整数具有特殊含义,因此我希望在创建时可以选择它们,然后再编辑。如果在创建时未给出整数,则自动递增,这将是理想的,否则使用指定的值。但可编辑的主要字段是我的主要需求。有没有办法在ASP.NET MVC 3中优雅地做到这一点?

7 个答案:

答案 0 :(得分:51)

使用这些数据注释选项:

  • [System.ComponentModel.DataAnnotations.KeyAttribute()]
  • [System.ComponentModel.DataAnnotations.DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]

答案 1 :(得分:27)

您可以使用FluentMapping:

modelBuilder.Entity<*entityname*>().Property(m => m.*fieldname*)
             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

答案 2 :(得分:3)

如果你想在EntityFramework Core 2.0中使用流畅的api,你可以写:

modelBuilder.Entity<*myEntity*>()
  .Property(e => e.*myFieldname*)
  .ValueGeneratedNever();

答案 3 :(得分:2)

我刚安装了最新的EntityFramework.dll 5.0.0版,我相信......

  然而,由于有一个运行版本,我有一半时间感到困惑   v4.0.30319和版本4.4.0.0但是,我确信从网站上我   在我的搜索中提到了(它告诉我通过&#34; Package安装   Mangager控制台&#34;您可以通过VS中的菜单进入   &#34;工具|库包管理器|包管理器控制台&#34;并输入   &#34; PM&gt;&#34;提示&#34; Install-Package EntityFramework [可选:版本   数字或-Pre为最新的预发布(测试版)]&#34;)它是   5.0.0。

...,并且有一个属性&#34; System.CompnentModel.DataAnnotations.DatabaseGenerated(Computed,Identity或None)(以前的版本)或[...]。Schema.DatabaseGenerated(最新版本)&# 34;你可以用的。所以要么使用这个属性,要么使用如上所述的流畅的映射思想(由William Haack编辑(由Remo Gloor编辑)),如果不是代码优先(即改变生产),那么如上所述(由Adam Tuliper),你将需要写和执行一个关闭脚本以关闭标识插入。最重要的是,如果您不提供ID,则可以通过在代码中检索表上的MAX(ID)+ 1(并记住多用户环境中的并发问题)或触发器来模拟身份插入。或者,如果你想插入漏洞,就像表达式一样,你可以在触发器中执行此操作,也可以拦截插入的行并检查ID列是否已设置,如果是,则继续插入,否则,  首先设置值。插入漏洞的一种方法是使用这个技巧(我在一些我不记得的网站上看到,所以我在这里猜一点)你从一些大桌面有效地做一个反内连接您的表中的单列rownumbers以查找第一个可用的未使用的标识号(即查找不是目标表成员的第一个rownumber)。

在SQL Server 2005及更高版本中:

CREATE TRIGGER updInsYourTable_PlugHolesOnIDIfNull 
ON YourTable
FOR update, insert AS
BEGIN
    DECLARE @ID INT
    SELECT @ID = ID FROM INSERTED
    IF @ID IS NULL
    BEGIN
        ;WITH CTE_StagedNumbers AS
        (
            SELECT ROW_NUMBER() OVER (ORDER BY o.object_id) AS NextFreeIdentity
            FROM (  SELECT object_id FROM sys.objects
                 -- UNION ALL 
                 -- SELECT object_id FROM sys.objects
                 /* NB: Here if sys.objects is not larger enough say on a small schema 
                    configured database then use a different table otherwise you can 
                    always union all on the same table as many times as you want to 
                    double, triple etc. its size. */
                 )  o
        )
        UPDATE YourTable
        SET ID = (
                    SELECT TOP 1 NextFreeIdentity
                    FROM CTE_StagedNumbers
                    WHERE NextFreeIdentity NOT IN (SELECT ID FROM YourTable)
                 )
        WHERE ID IS NULL
    END
END
GO

注意,CTE_StagedNumbers不是必需的,它只是用于强调,主要技巧不一定是设置行号,但是,如果你要设置一个永久的临时表(比如说StagedNumbers)一个没有自动标识的单个整数列(比如NextFreeIdentity INT NOT NULL PRIMARY KEY),(除了NB:你的ID列的YourTable定义必须接受null,因为我们使用的是后触发器)预先填充了连续的正数 - 使用上述技术从1开始的整数值,然后完全删除CTE并用StagedNumbers替换最终选择中的CTE_StagedNumbers,那么这将是最有效的。

答案 4 :(得分:1)

如果这是数据库中的标识字段,则无法进行。那么你可以通过在数据库端设置身份插入,但通过良好的实践,除非批量插入记录,否则你不应该这样做。如果您不希望将此作为标识,请在该列的DB中将identity选项设置为false。

答案 5 :(得分:1)

使用属性:

public class MessageSubject
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }
        public string Title { get; set; }
        public string Comment { get; set; }
        public bool BuildIn { get; set; }
    }

答案 6 :(得分:0)

从外键表中删除“必需”属性对我来说是成功的。

相关问题