从多个 table 审计日志记录到单个 EF 审计 table 时出现无效的转换异常
Invalid cast exception when audit logging from multiple tables to a single EF audit table
我的应用程序使用 Audit.NET
和 Audit.EntityFramework
来审核日志数据更改。为了促进审计日志/数据更改可视化的创建,我决定将更改从几个表记录到一个表中。长话短说:我为我的项目定义了一个状态机,我记录了从它第一次出现在我的系统中到我处理它时发生的事情。
为了展示我正在努力解决的问题,我创建了一个测试 REST 应用程序并在 GitHub repository 上提供了它。
应用程序跟踪文章的生命周期,文章可以通过以下方式进入系统:
- 一篇文章被直接添加并链接到一个出版物——简而言之,它是已接受
- 增加了一条提案——简而言之,就是PROPOSED
- 可以接受拟议文章以添加到出版物中 - 简而言之,它是 ACCEPT_PROPOSAL
有关更多详细信息,请查看 public enum ProcessAction
。
如何重现
- 克隆存储库
- 创建数据库和用户 - 创建 SQL 代码包含在
TestDbContext.cs
的注释中
- 运行数据库迁移
- 启动应用程序
- 按照出现的顺序从
TestsController.cs
调用所有端点 - 这里是直接链接 (HTTP GET
):
- 喵喵出版:http://localhost:5000/tests/publication/add?name=New%20Publication
- 添加文章:http://localhost:5000/tests/article/add?type=ReviewArticle&title=Test%20article%202018¬e=My%20test%20note&publicationId=1
- 提出文章:http://localhost:5000/tests/proposal/add?type=ReviewArticle&title=Test提案1¬e=Proposal%20note%201
- 接受文章提议(注意:文章 ID 在您的系统上可能不同):http://localhost:5000/tests/accept/1?publicationId=2
问题
最后一次调用抛出以下异常:
InvalidCastException: Unable to cast object of type
'si.dezo.test.DotNetAudit.Models.Article' to type
'si.dezo.test.DotNetAudit.Models.ArticleProposal'.
我把TestDbContext.cs
中的几行代码注释掉,标记为
NOTE: the below is not working
是我做错了什么,还是库的限制或错误?
有解决办法吗?
问题是库只支持对每种目标类型(审计类型)执行一项操作。
当您用这样的操作调用 .Map
时:
.Map<Article, Audit_Article>((evt, entry, auditTbl) => { /*some action*/ })
它将存储与类型Audit_Article
相关的操作,但您的下一次调用:
.Map<ArticleProposal, Audit_Article>((item, auditTbl) => { /*overriding action*/ })
将覆盖您之前对映射到 Audit_Article
的任何类型的操作。
所以我最初的建议是通过 .AuditEntityAction<IAudit>
使用常用操作。这会给您带来任何问题吗?
我认为可以扩展库以允许将多个类型映射到同一目标类型,每个类型都有独立的操作。我去看看
更新
这已在 Audit.EntityFramework 版本 13.2.0 上实现,您现在可以让多个实体映射到相同的审计类型,每个实体都有独立的操作。
我的应用程序使用 Audit.NET
和 Audit.EntityFramework
来审核日志数据更改。为了促进审计日志/数据更改可视化的创建,我决定将更改从几个表记录到一个表中。长话短说:我为我的项目定义了一个状态机,我记录了从它第一次出现在我的系统中到我处理它时发生的事情。
为了展示我正在努力解决的问题,我创建了一个测试 REST 应用程序并在 GitHub repository 上提供了它。
应用程序跟踪文章的生命周期,文章可以通过以下方式进入系统:
- 一篇文章被直接添加并链接到一个出版物——简而言之,它是已接受
- 增加了一条提案——简而言之,就是PROPOSED
- 可以接受拟议文章以添加到出版物中 - 简而言之,它是 ACCEPT_PROPOSAL
有关更多详细信息,请查看 public enum ProcessAction
。
如何重现
- 克隆存储库
- 创建数据库和用户 - 创建 SQL 代码包含在
TestDbContext.cs
的注释中
- 运行数据库迁移
- 启动应用程序
- 按照出现的顺序从
TestsController.cs
调用所有端点 - 这里是直接链接 (HTTP GET
):- 喵喵出版:http://localhost:5000/tests/publication/add?name=New%20Publication
- 添加文章:http://localhost:5000/tests/article/add?type=ReviewArticle&title=Test%20article%202018¬e=My%20test%20note&publicationId=1
- 提出文章:http://localhost:5000/tests/proposal/add?type=ReviewArticle&title=Test提案1¬e=Proposal%20note%201
- 接受文章提议(注意:文章 ID 在您的系统上可能不同):http://localhost:5000/tests/accept/1?publicationId=2
问题
最后一次调用抛出以下异常:
InvalidCastException: Unable to cast object of type 'si.dezo.test.DotNetAudit.Models.Article' to type 'si.dezo.test.DotNetAudit.Models.ArticleProposal'.
我把
TestDbContext.cs
中的几行代码注释掉,标记为NOTE: the below is not working
是我做错了什么,还是库的限制或错误?
有解决办法吗?
问题是库只支持对每种目标类型(审计类型)执行一项操作。
当您用这样的操作调用 .Map
时:
.Map<Article, Audit_Article>((evt, entry, auditTbl) => { /*some action*/ })
它将存储与类型Audit_Article
相关的操作,但您的下一次调用:
.Map<ArticleProposal, Audit_Article>((item, auditTbl) => { /*overriding action*/ })
将覆盖您之前对映射到 Audit_Article
的任何类型的操作。
所以我最初的建议是通过 .AuditEntityAction<IAudit>
使用常用操作。这会给您带来任何问题吗?
我认为可以扩展库以允许将多个类型映射到同一目标类型,每个类型都有独立的操作。我去看看
更新
这已在 Audit.EntityFramework 版本 13.2.0 上实现,您现在可以让多个实体映射到相同的审计类型,每个实体都有独立的操作。