EF6 和 MVC5:使用两个字段作为组合键
EF6 and MVC5: Using two fields as a combined key
我有几个对象(Product、Rule、PriceDetail 等)在 CRUD 应用程序中管理和存储信息。我想要一种记录数据更新时间的方法,为此我创建了一个更新 class,在每个数据 class.[=15 中引用为 ICollection<Update> Updates
=]
当table全部生成后,EF在更新table中为每个class创建一个FK(Product_ID、Rule_ID等.).这似乎非常低效。我可以使用双字段键,例如 enum ObjectType
和 long ID
吗?或者,我可以使用 string ID
并强制使用字符串的前 N 个字符标识引用对象的模式吗?如果是后者,数据库可以自增字符串值吗?
这里是一些示例代码,经过修剪以放置在这里:
public class Update
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public string Reason { get; set; }
public DateTime TimeOfUpdate { get; set; }
public long Product_ID { get; set; }
public long Rule_ID { get; set; }
}
public class Product
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public string Name { get; set; }
public PriceDetail Price { get; set; }
public ICollection<Update> Updates { get; set; }
}
public class Rule
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public string Name { get; set; }
public ICollection<Condition> Conditions { get; set; }
public ICollection<Update> Updates { get; set; }
}
有多种处理审计逻辑的方法。
- 您是否希望存储每个 table 的更新历史记录?如果将其限制为几个 table,您的设计可能会正常工作。但是,如果您想更新许多 table,您可能想尝试以下选项。
- 包括 3 tables(产品、更新和 ProductUpdates)。 Products tables 将始终具有最新数据。每次更新 Products 中的条目时,Updates tables 将获得一个新行来捕获更新的时间戳。 ProductUpdates 将有一个指向 Updates table 的外键,并且会有来自 Products table 的旧行。这样您就可以确切地知道该行在任何时间点的内容。将其扩展到任何其他 table X 将需要添加 XUpdates table。但是你不会有你提到的不必要的 50 个外键。
- 另一种选择是在 table 中添加 IsActive、UpdatedBy、UpdatedTimestamp 等列。每次更新一行时,将其标记为不活动并插入包含最新数据的新行。如果需要,您还可以存储原因和规则列。
- 您还可以重新设计您的实体,使其主键成为更新的外键 table。这样您将消除所有先前解决方案的不雅之处。每次更新时,您都会在 Updates table 中插入一行,并使用生成的 Id 作为产品中新行的主键 table.
- Entity Framework 可以帮助您自动化第 3 点和第 4 点中列出的过程。基本思想是拦截更新的保存请求并强制执行更新和插入。
- 最后,您还可以使用 CLR 触发器来获得所需的审计功能。
每种解决方案都有其优点和缺点。最适合您的解决方案取决于您的具体用例。
我有几个对象(Product、Rule、PriceDetail 等)在 CRUD 应用程序中管理和存储信息。我想要一种记录数据更新时间的方法,为此我创建了一个更新 class,在每个数据 class.[=15 中引用为 ICollection<Update> Updates
=]
当table全部生成后,EF在更新table中为每个class创建一个FK(Product_ID、Rule_ID等.).这似乎非常低效。我可以使用双字段键,例如 enum ObjectType
和 long ID
吗?或者,我可以使用 string ID
并强制使用字符串的前 N 个字符标识引用对象的模式吗?如果是后者,数据库可以自增字符串值吗?
这里是一些示例代码,经过修剪以放置在这里:
public class Update
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public string Reason { get; set; }
public DateTime TimeOfUpdate { get; set; }
public long Product_ID { get; set; }
public long Rule_ID { get; set; }
}
public class Product
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public string Name { get; set; }
public PriceDetail Price { get; set; }
public ICollection<Update> Updates { get; set; }
}
public class Rule
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
public string Name { get; set; }
public ICollection<Condition> Conditions { get; set; }
public ICollection<Update> Updates { get; set; }
}
有多种处理审计逻辑的方法。
- 您是否希望存储每个 table 的更新历史记录?如果将其限制为几个 table,您的设计可能会正常工作。但是,如果您想更新许多 table,您可能想尝试以下选项。
- 包括 3 tables(产品、更新和 ProductUpdates)。 Products tables 将始终具有最新数据。每次更新 Products 中的条目时,Updates tables 将获得一个新行来捕获更新的时间戳。 ProductUpdates 将有一个指向 Updates table 的外键,并且会有来自 Products table 的旧行。这样您就可以确切地知道该行在任何时间点的内容。将其扩展到任何其他 table X 将需要添加 XUpdates table。但是你不会有你提到的不必要的 50 个外键。
- 另一种选择是在 table 中添加 IsActive、UpdatedBy、UpdatedTimestamp 等列。每次更新一行时,将其标记为不活动并插入包含最新数据的新行。如果需要,您还可以存储原因和规则列。
- 您还可以重新设计您的实体,使其主键成为更新的外键 table。这样您将消除所有先前解决方案的不雅之处。每次更新时,您都会在 Updates table 中插入一行,并使用生成的 Id 作为产品中新行的主键 table.
- Entity Framework 可以帮助您自动化第 3 点和第 4 点中列出的过程。基本思想是拦截更新的保存请求并强制执行更新和插入。
- 最后,您还可以使用 CLR 触发器来获得所需的审计功能。
每种解决方案都有其优点和缺点。最适合您的解决方案取决于您的具体用例。