【问题标题】:Entity Framework 5: Using DatabaseGeneratedOption.Computed option实体框架 5:使用 DatabaseGeneratedOption.Computed 选项
【发布时间】:2013-07-10 03:34:03
【问题描述】:

我有一个使用 [DatabaseGenerated(DatabaseGeneratedOption.Computed)] 属性的 EF5 代码优先项目。
此选项会覆盖我的设置。

考虑这个 SQL 表:

CREATE TABLE Vehicle (
  VehicleId  int identity(1,1) not null,
  Name varchar(100) not null default ('Not Set')
)

我正在使用 SQL 默认构造来设置 [Name] 以防它未设置。

在后面的代码中,我定义了一个类,类似于:

public class Vehicle {
   ...

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public string ShoulderYN { get; set; }
}

当我在代码中更新实体时,默认设置的值会覆盖我的新设置。

在代码中,我有(伪):

vehicle.Name = 'Update Name of Vehicle';
_dbContext.Update(vehicle);
_dbContext.SaveChanges();

预期结果是Vehicle.Name = 'Update Name of Vehicle'
实际结果是Vehicle.Name = 'Not Set'

EF5 中有没有办法说:
如果 Vehicle.Name 为空/空,则使用数据库中定义的值?否则,如果我在代码中设置了值,我想使用这个值。

【问题讨论】:

    标签: ef-code-first entity-framework-5


    【解决方案1】:

    显然,没有。没那么聪明:)

    您可能已经阅读过,Computed 选项只是告诉 EF 不要更新您的列,因为您将自己在 DB 端计算一个值。然后,EF 将只从您的数据库中返回新计算的值(在您的情况下为“未设置”)。

    您的三个基本选项是 - 根据 EF 源代码文档:

    • 无 - 数据库不生成值。
    • 标识 - 插入一行时数据库生成一个值。
    • 已计算 - 数据库在插入或更新行时生成一个值。

    https://github.com/aspnet/EntityFramework6/blob/527ae18fe23f7649712e9461de0c90ed67c3dca9/src/EntityFramework/DataAnnotations/Schema/DatabaseGeneratedOption.cs

    由于您希望完成更多自定义逻辑,恐怕您必须自己完成。我建议您停止依赖数据库默认约束,并以代码优先的方式做所有事情。这样你就会有这样的代码:

    public class Vehicle
    {
      public Vehicle()
      {
        this.Name = "Not set";
      }
      
      // Without 'Generated' attribute
      public string Name { get; set; }
    }
    

    这样,当您的实体被创建时,它会自动以预期的默认值开始。并且可以在以后通过简单地修改 Name 属性进行更改。

    希望对你有帮助!

    【讨论】:

      【解决方案2】:

      我检查了几个小时以获得好的答案,但没有: EF 无法通过自动生成的 ID 更新模型。

      您有 3 个选项:

      1. 向车辆模型添加另一个 VehicleId。
      2. 将自动生成的 ID 更改为由您手动生成。
      3. 将唯一标识符设置为其他内容,然后是生成的 ID 模型。 在您的 Vehicle Class 中,它可以是 Name 属性。

      我建议你选择 3: 将唯一 ID 设置为 Vehicle.Name(您可以添加更多属性)。 然后:如果唯一ID的车辆不存在,则将新车辆添加到db-context:

      //if there is no such a Vehicle in system, add it:
      if (vehicle.Name !=null && vehicle.Name != String.Empty && _dbContext.Where(v => v.Name == vehicle.Name).FirstOrDefault() == null)
          _dbContext.Add(vehicle);
      
      _dbContext.SaveChanges();
      

      【讨论】:

        【解决方案3】:

        其实有一个简单的解决方案:

        • 您需要在表创建脚本中保留默认约束值,就像现在一样:

          CREATE TABLE Vehicle (
            VehicleId  int identity(1,1) not null,
            Name varchar(100) not null default ('Not Set')
          )
          
        • 只需从类定义中的属性中删除DatabaseGenerated 属性:

          public class Vehicle {
             ...
          
             [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
             public string ShoulderYN { get; set; }
          }
          

        就是这样:现在数据库将仅在您未在代码中指定某些值时使用默认值。希望这会有所帮助。

        【讨论】:

        • 为什么默认不提供这种行为?这背后有什么好处?例如,我在 DB 的表列中确定默认日期(notnull)。但是如果代码没有发送值,EF 会发送一个最小日期时间。我真的找不到任何逻辑。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-28
        • 1970-01-01
        相关资源
        最近更新 更多