Столбцы XML в приложении Code-First
Я пытаюсь создать столбец XML в Code First. Мне хорошо известно, что Entity Framework не полностью поддерживает столбцы XML и читает их как строку. Это здорово. Тем не менее, мне бы хотелось, чтобы тип столбца был XML. Здесь мой класс:
class Content
{
public int ContentId { get; set; }
[Column(TypeName="xml")]
public string XmlString { get; set; }
[NotMapped]
public XElement Xml { get { ... } set { ... } }
}
Проблема в том, что First Migrations кода полностью игнорирует атрибут Column и создает поле как nvarchar(max)
. Я попытался использовать [DataType("xml")]
, но это тоже не сработало.
Является ли это ошибкой миграции?
Ответы
Ответ 1
Вы пробовали:
public String XmlContent { get; set; }
public XElement XmlValueWrapper
{
get { return XElement.Parse(XmlContent); }
set { XmlContent = value.ToString(); }
}
public partial class XmlEntityMap : EntityTypeConfiguration<XmlEntity>
{
public FilterMap()
{
// ...
this.Property(c => c.XmlContent).HasColumnType("xml");
this.Ignore(c => c.XmlValueWrapper);
}
}
Ответ 2
Я достиг того, что нужно с атрибутом, и я присвоил свой класс xml-поля атрибуту.
[XmlType]
public string XmlString { get; set; }
[NotMapped]
public XElement Xml
{
get { return !string.IsNullOrWhiteSpace(XmlString) ? XElement.Parse(XmlString) : null; }
set {
XmlString = value == null ? null : value.ToString(SaveOptions.DisableFormatting);
}
}
Получил помощь из этих двух статей:
https://entityframework.codeplex.com/wikipage?title=Code%20First%20Annotations
https://andy.mehalick.com/2014/02/06/ef6-adding-a-created-datetime-column-automatically-with-code-first-migrations/
Решение
Определить атрибут
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class XmlType : Attribute
{
}
Атрибут регистрации в контексте
В "OnModelCreating" контекста
modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<XmlType, string>("XmlType", (p, attributes) => "xml"));
Пользовательский генератор Sql
public class CustomSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(ColumnModel column, IndentedTextWriter writer)
{
SetColumnDataType(column);
base.Generate(column, writer);
}
private static void SetColumnDataType(ColumnModel column)
{
// xml type
if (column.Annotations.ContainsKey("XmlType"))
{
column.StoreType = "xml";
}
}
}
Регистрация пользовательского генератора Sql
В конструкторе конфигурации миграции зарегистрируйте собственный генератор SQL.
SetSqlGenerator("System.Data.SqlClient", new CustomSqlGenerator());
Ответ 3
Но что, если XmlContent имеет значение null?
Возможно:
public XElement XmlValueWrapper
{
get { return XmlContent != null ? XElement.Parse(XmlContent) : null; }
set { XmlContent = value.ToString(); }
}