如何构建绑定含XML列SQL表的数据模型(ASP.NET Core+EF Core)
解决EF Core读取含XML列SQL表的主键错误问题
你遇到的问题根源在于EF Core把SqlXml类型识别成了一个需要独立映射的实体类型,而不是一个简单的数据库列类型,所以它要求你给这个"实体"定义主键——但这显然不是你的本意。
下面是两种可行的解决方案,推荐使用第二种(强类型XML操作):
方案1:将XML列映射为字符串类型
把模型中的SqlXml替换成string,然后告诉EF Core这个属性对应数据库的xml列:
修改后的模型
public class ShWorkflowRunsModel { [Key] public Int64 runId { get; set; } public Guid serviceId { get; set; } public string serviceName { get; set; } public Guid workflowId { get; set; } // 把SqlXml改成string public string workflowConfig { get; set; } public DateTime startTime { get; set; } public DateTime endTime { get; set; } public bool isScheduled { get; set; } public string errorMessage { get; set; } public bool hasErrorCounters { get; set; } }
配置DbContext的列类型
在OnModelCreating中添加属性映射配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ShWorkflowRunsModel>() .ToTable("sh_workflowRuns") // 指定workflowConfig对应xml类型的列 .Property(x => x.workflowConfig) .HasColumnType("xml"); }
方案2:将XML列映射为XDocument类型(推荐)
如果你需要在代码中操作XML的内容,用System.Xml.Linq.XDocument会更方便,EF Core可以自动处理它和数据库xml列的序列化/反序列化:
修改后的模型
using System.Xml.Linq; public class ShWorkflowRunsModel { [Key] public Int64 runId { get; set; } public Guid serviceId { get; set; } public string serviceName { get; set; } public Guid workflowId { get; set; } // 替换为XDocument public XDocument workflowConfig { get; set; } public DateTime startTime { get; set; } public DateTime endTime { get; set; } public bool isScheduled { get; set; } public string errorMessage { get; set; } public bool hasErrorCounters { get; set; } }
配置DbContext的列类型
同样需要指定列类型为xml:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ShWorkflowRunsModel>() .ToTable("sh_workflowRuns") .Property(x => x.workflowConfig) .HasColumnType("xml"); }
额外优化建议
你的GetShWorkflowRuns方法中,把Guid转换成字符串再比较的写法可以优化一下,直接解析参数为Guid后比较,性能更好也更严谨:
public List<ShWorkflowRunsModel> GetShWorkflowRuns(string workflowId) { var targetWorkflowId = Guid.Parse(workflowId); return _context.shWorkflowRuns.Where(wr => wr.workflowId == targetWorkflowId).ToList(); }
内容的提问来源于stack exchange,提问作者Paul Shepherd
相关产品推荐
相关产品推荐

