【问题标题】:How to get EF to recognize a SQL Server column as Computed?如何让 EF 将 SQL Server 列识别为已计算?
【发布时间】:2016-09-25 10:59:12
【问题描述】:

我首先使用数据库。

我希望创建一个列来存储记录的LastModified 日期时间。此列应默认为GetUTCDate(),当行被修改时,设置为GetUTCDate()

我可以使用桌子上的触发器来完成后者。

但是,当使用 Entity Framework 插入记录时,默认情况下它会在 LastModified 列中发送 0 日期,随后该列的默认约束被忽略,值设置为 0。

我可以手动更改 .edmx 文件中列的 StoreGeneratedPattern 属性。但是,我希望 Entity Framework 自动执行此操作 - 如果它上线,那么我依靠内存来工作。

有没有办法在 SQL Server 中配置列,使实体框架在插入记录时永远不会发送值(我相信这可以使用计算列来实现)?

【问题讨论】:

    标签: c# sql-server entity-framework timestamp


    【解决方案1】:

    您的EDMX 只是一个XML 文件。您可以创建一些简单的控制台应用程序,例如 EDMXFixer.exe,您可以在构建事件上运行并编辑您的文件。我们在所有表中都有一些公共列CreatedDate,默认值为getdate()。所以我只是编辑EDMX 文件并将所有这些列设为StoreGeneratedPattern = Computed

    然后我在我的预构建活动中有这个:

    "$(ProjectDir)EDMXFixer.exe" "$(ProjectDir)DatabaseObjects\test.edmx"
    

    修复程序的代码如下所示:

    static void Main(string[] args)
    {
        int i;
        int count;
    
        XmlAttribute xmlAttribute;
    
        if ((args == null ? false : (int)args.Length != 0))
        {
            string str = args[0];
            bool flag = false;
    
            if (File.Exists(str))
            {
                FileInfo fileInfo = new FileInfo(str);
                if ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                {
                    fileInfo.Attributes = (FileAttributes)(Convert.ToInt32(fileInfo.Attributes) - Convert.ToInt32(FileAttributes.ReadOnly));
                    flag = true;
                }
    
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(str);
    
                if (xmlDocument.DocumentElement != null)
                {
                    count = xmlDocument.DocumentElement.ChildNodes[1].ChildNodes[1].ChildNodes[0].ChildNodes.Count;
                    for (i = 0; i < count; i++)
                    {
                        if (xmlDocument.DocumentElement != null)
                        {
                            foreach (XmlNode childNode in xmlDocument.DocumentElement.ChildNodes[1].ChildNodes[1].ChildNodes[0].ChildNodes[i].ChildNodes)
                            {
                                if ((childNode.Name != "Property" ? false : childNode.Attributes != null))
                                {
                                    if ((childNode.Attributes["Name"].Value != "CreatedDate" ? false : childNode.Attributes["Type"].Value == "datetime"))
                                    {
                                        xmlAttribute = xmlDocument.CreateAttribute("StoreGeneratedPattern");
                                        xmlAttribute.Value = "Computed";
                                        childNode.Attributes.Append(xmlAttribute);
                                    }
                                }
                            }
                        }
                    }
                }
                if (xmlDocument.DocumentElement != null)
                {
                    count = xmlDocument.DocumentElement.ChildNodes[1].ChildNodes[3].ChildNodes[0].ChildNodes.Count;
                    for (i = 0; i < count; i++)
                    {
                        if (xmlDocument.DocumentElement != null)
                        {
                            foreach (XmlNode xmlNodes in xmlDocument.DocumentElement.ChildNodes[1].ChildNodes[3].ChildNodes[0].ChildNodes[i].ChildNodes)
                            {
                                if ((xmlNodes.Name != "Property" ? false : xmlNodes.Attributes != null))
                                {
                                    if ((xmlNodes.Attributes["Name"].Value != "CreatedDate" ? false : xmlNodes.Attributes["Type"].Value == "DateTime"))
                                    {
                                        xmlAttribute = xmlDocument.CreateAttribute("annotation", "StoreGeneratedPattern", "http://schemas.microsoft.com/ado/2009/02/edm/annotation");
                                        xmlAttribute.Value = "Computed";
                                        xmlNodes.Attributes.Append(xmlAttribute);
                                    }
                                }
                            }
                        }
                    }
                }
                xmlDocument.Save(str);
                if (flag)
                {
                    fileInfo.Attributes = (FileAttributes)(Convert.ToInt32(fileInfo.Attributes) + Convert.ToInt32(FileAttributes.ReadOnly));
                }
            }
        }
    }
    

    您只需根据需要稍微更改一下即可。

    【讨论】:

      【解决方案2】:

      数据库第一种情况:计算列是只读数据,您必须知道您不能在该列中写入,就像您必须知道在数据库的每一列中写入什么数据一样。

      代码第一种情况: 这里是代码优先对象中计算列的示例 请注意注解DatabaseGeneratedOption.Computed

      public class UserProfile
      {
           public int Id { get; set; }
      
           public string FirstName { get; set; }
           public string LastName { get; set; }
      
           [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
           public string FullName { get; private set; }
      }
      

      FullName 属性需要 DatabaseGenerated 属性。这是让 Entity Framework Code First 知道数据库将为我们计算此属性的提示。

      【讨论】:

      • OP 具有数据库优先模型。
      • 如果您从数据库中更新您的 EDMX,您将失去一切,必须再次进行这些更改。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 2010-10-15
      • 1970-01-01
      • 2011-05-04
      • 2021-07-25
      • 2016-11-26
      相关资源
      最近更新 更多