繁体   English   中英

实体框架-将文档快照保存在SQL数据库中

[英]Entity Framework - Saving a snapshot of a document in a SQL database

背景信息我正在使用EF6,可以随意更改数据库。

我今天遇到了这个问题。 说我有:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
}

public class Invoice
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public int AddressId { get; set; }
    public bool IsCompleted { get; set; }
}

允许用户更新CompanyAddress 还允许用户更新Invoice 但是由于是财务文件,因此如果用户将IsCompleted标记为true,则必须以某种方式保存该地址的快照。

当前,它是通过以下方式完成的:

public class Invoice
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public int AddressId { get; set; }
    public bool IsCompleted { get; set; }

    //Auditing fields 
    public string CompanyName { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
}

我认为这很难遵循。 我刚在想:

选项1:将审核保存到自己的审核表中:

public class Invoice
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public int AddressId { get; set; }
    public bool IsCompleted { get; set; }

    //Null if IsCompleted = false. 
    public DateTime? CompletedTimeStamp { get; set; }
}

public class CompanyAudit
{
    public int CompanyId { get; set; }
    public string Name { get; set; }
    public DateTime TimeStamp { get; set; }
}

public class AddressAudit
{
    public int AddressId { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public DateTime TimeStamp { get; set; }
}

但是,如果我们确实更改了Company和Address的架构,那么这似乎要创建许多表,并且需要进行大量工作。 另外,它也不是很健壮。 没有大量的接线,我无法将其用于其他文档。 但是,这是我主要在互联网上发现的东西。 每个表一个审计表。

选项2:将所有审核保存到同一表中:

public class Audit
{
    public int DocumentId { get; set; }
    public string DocumentType { get; set; }
    public string JsonData { get; set; }
    public DateTime TimeStamp { get; set; }
}

但是,这似乎不是很标准。 我以前从未将Json数据保存到SQL数据库。 这不好吗? 如果是这样,可能会出什么问题?

我应该选择选项1还是选项2?

简短答案

假设您使用的是SQL Server,建议您为该作业创建一些可序列化XML的DTO ,并使用XML数据类型将XML存储在专用列中

答案稍长

我已经走了完全相同的道路。 我们需要在已打印出数据时保存快照,其中涉及许多表,在该过程中可能会重复这些快照。

要求与评估

我们不想合并其他技术(例如,由Andreas提出的文件系统或某些NoSQL /文档数据库),而是将所有内容存储在SQL Server中,否则会带来复杂的备份方案,部署,维护等。

我们想要一些容易理解的东西。 新的开发人员应该熟悉所使用的技术。 架构不应受到太大影响。

对于序列化,有几个选项: XMLJSONBinaryFormatterDataContractSerializer协议缓冲区。 ..我们的要求:易于版本控制(用于添加的属性或关系),可读性,与SQL Server的一致性。

使用所有提到的格式应该可以轻松地进行版本控制。 可读性:XML和JSON在这里胜出。 与SQL Server的一致性: SQL Server本身支持XML ,这是我们的选择。

履行

我们做了几件事:

  1. 与现有实体并排在我们的数据库项目中创建其他DTO ,而不是用于EF,而是用于XML序列化。 它们使用XmlAttributes进行注释,类似于一个复杂的自包含结构,其中包含保存文档数据所需的一切。 InvoiceSnapshot类具有ParseToXml方法以支持序列化。

  2. 在需要时更新我们的实体以包括快照:

     public string InvoiceXml { get; set; } public InvoiceSnapshot Invoice { get { return this.InvoiceXml != null ? InvoiceSnapshot.Parse(this.InvoiceXml) : null; } set { this.InvoiceXml = value != null ? value.ToXml() : null; } } 
  3. 更新实体配置以创建XML列,并忽略InvoiceSnapshot属性:

     public class InvoiceEntityConfig : EntityTypeConfiguration<InvoiceEntity> { public InvoiceEntityConfig() { this.Property(c => c.InvoiceXml).HasColumnType("xml"); this.Ignore(c => c.Invoice); } } 
  4. 修改我们的业务对象,以便它们从实体(可编辑状态)或XML-DTO(快照,只读状态)加载自身。 我们在有助于简化流程的两个界面上都使用接口。

进一步的步骤

  • 您应该在单独的标量列中添加常见查询的元数据,并为它们建立索引。 仅当您确实要显示发票时才检索xml数据。
  • 您可以研究SQL Server可以为XML做些什么 ,尤其是当您需要基于属性进行查询时。 它可以为它们建立索引,并且可以在查询中使用XPath。
  • 对XML进行签名或哈希处理,以确保不会篡改快照数据。

选项2

更好的方法是将生成的发票(pdf)及其所有还原版本存储在普通文件中。

您仍然可以使用Invoice表,但是如果某些客户数据发生更改并且用户重新打印了较旧的文档,则无需担心。

要存储生成的文档,几乎就像将模型存储在JsonData中一样,但是您不需要保护模板和模板生成器的版本。

Option1只是蛮力的,最好用“事件存储”,“事件源”和“查询和命令”模式发布。

public class Document //or DocumentFile
{
    public int DocumentId { get; set; }
    public string DocumentType { get; set; }
    public string FilePath { get; set; }
    [Index]
    public String Owner { get; set;} //exp. "Customer:Id", "Contact:Id"  maybe just int
    [Index]
    public String Reference { get; set; } //exp. "Invoice:Id", "Contract:Id"   maybe just int
    public DateTime TimeStamp { get; set; } //maybe int Reversion
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM