2

为了尝试隔离错误的来源,我构建了以下内容:

SQL Server 表:

 CREATE TABLE [dbo].[Names]
  ([Key] [uniqueidentifier] NOT NULL,
   [Name] [nvarchar](50) NULL,  
   CONSTRAINT [PK_Names] PRIMARY KEY CLUSTERED ([Key] ASC)
  )
 GO

 ALTER TABLE [dbo].[Names] ADD CONSTRAINT [DF_Names_Key] DEFAULT (newid()) FOR [Key] 

当我通过 SQL Server Management Studio 向该表添加行时,guid 会按预期获得一个值。

然后我用这个表创建了一个 EF 模型,这生成了以下代码:

/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmEntityTypeAttribute(NamespaceName="Model1", Name="Names")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Names : EntityObject
{
    #region Factory Method

    /// <summary>
    /// Create a new Names object.
    /// </summary>
    /// <param name="key">Initial value of the Key property.</param>
    public static Names CreateNames(global::System.Guid key)
    {
        Names names = new Names();
        names.Key = key;
        return names;
    }

    #endregion

    #region Primitive Properties

    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Guid Key
    {
        get
        {
            return _Key;
        }
        set
        {
            if (_Key != value)
            {
                OnKeyChanging(value);
                ReportPropertyChanging("Key");
                _Key = StructuralObject.SetValidValue(value);
                ReportPropertyChanged("Key");
                OnKeyChanged();
            }
        }
    }
    private global::System.Guid _Key;
    partial void OnKeyChanging(global::System.Guid value);
    partial void OnKeyChanged();

    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
    [DataMemberAttribute()]
    public global::System.String Name
    {
        get
        {
            return _Name;
        }
        set
        {
            OnNameChanging(value);
            ReportPropertyChanging("Name");
            _Name = StructuralObject.SetValidValue(value, true);
            ReportPropertyChanged("Name");
            OnNameChanged();
        }
    }
    private global::System.String _Name;
    partial void OnNameChanging(global::System.String value);
    partial void OnNameChanged();

然后我创建了一个测试来向表中添加数据:

    [TestMethod]
    public void WriteTestMethod1()
    {
        using (Model1Container context = new Model1Container())
        {
            Names n = new Names();
            n.Name = "T2";

            context.Names.AddObject(n);
            context.SaveChanges();
        }

    }

结果是插入了行,但 Guid 为空(全为零)

为什么会这样?EF 可以与数据库生成的 Guid 一起使用吗?

4

1 回答 1

0

这是旧的,但无论如何这是一个答案,因为它仍然相关。

  • 您的测试代码创建一个实例class Names并为该Name属性分配一个值。
  • 您没有明确地将任何内容分配给 Key 属性。Key 属性是 Guid 类型,它是一个结构(值类型),而不是一个类(引用类型),所以它永远不能为空,并且总是有一个值,如果只是默认值的话。Guid 的未初始化默认值是全零字段。
  • 当您添加/保留此实体实例时,EF 会为这两个字段生成一个 INSERT,因为这两个字段都存在值。
  • 未使用架构中定义的默认值表达式,因为在客户端的 INSERT 语句中提供了值。

您可以通过将 Key 字段定义为可为空来获取服务器生成的 uid 值,这将对应于 C# 中的字段类型Guid?(而不是Guid)。然后,您可以允许 Key 值在您的代码中保持为空,并且将使用服务器定义的默认表达式。

但是,如果此字段是您的主键,则可为空的字段可能不是您所需要的。当我处于这种情况时,我使用一个构造函数来设置 Guid 值(是的,在客户端),而不是允许它采用默认值。

于 2019-02-07T16:38:22.020 回答