【问题标题】:Entity Framework: DataTable as XML string实体框架:DataTable 作为 XML 字符串
【发布时间】:2015-11-12 20:22:40
【问题描述】:

我目前正在使用一个简单的二进制格式化程序来存储我的应用程序的数据。我想从二进制格式化程序转移到 SQL 实现,原因如下:

  • 在公共数据源上启用应用程序的并发使用
  • 摆脱“专有”格式,这种格式很容易损坏并且可能无法从其他平台/应用程序(甚至其他程序集)访问

我首先实现实体框架代码来设计我的数据库。我的问题围绕着 DataTable 字段的存储。假设我有以下对象:

public class Person
{
    public string Name {get;set;}
    public DataTable TableOfInformation {get;set;}
}

将字符串“名称”保存到列中非常简单。为了保存数据表,我尝试转换为数据表条目列表。目前我倾向于简单地使用 XML 序列化并将 DataTable 保存为字符串列。

这是保存 DataTable 字段的最佳方式吗?这种方式有什么问题吗?

【问题讨论】:

  • DataTable 确实不是为与 EF 一起使用而设计的。只需将您的数据反序列化为 POCO 对象,这将更容易使用 Code First。
  • 您应该更进一步,并将 DataTable 存储为数据库表。
  • 您可以使用DataTable.WriteXml 方法将DataTable 转换为XML。但是,这无论如何都是错误的方法。

标签: c# xml entity-framework datatable


【解决方案1】:

我不建议将DataTable 存储为字段。创建一个实际的表更有意义。话虽这么说,如果您仍然希望继续这样做,那真的没那么难。这是一个例子:

public class Person
{
    public string Name { get; set; }

    public string TableOfInformationXml { get; set; }

    [NotMapped] // <-- This is important, since you will only store the TableOfInformationXml field
    public DataTable TableOfInformation
    {
        get
        {
            if (string.IsNullOrWhiteSpace(TableOfInformationXml))
            {
                return new DataTable();
            }
            var set = new DataSet();
            using (var reader = new StringReader(TableOfInformationXml))
            {
                set.ReadXml(reader);
            }
            return set.Tables[0];
        }
        set
        {
            var set = new DataSet();
            set.Tables.Add(value);
            var sb = new StringBuilder();
            using (var stringWriter = new StringWriter(sb))
            {
                set.WriteXml(stringWriter);
            }
            TableOfInformationXml = sb.ToString(); 
        }
    }
}

仅供参考:您也可以考虑将其存储为 JSON 而不是 XML...在这种情况下,请使用以下内容:

[NotMapped]
public DataTable TableOfInformation
{
    get
    {
        if (string.IsNullOrWhiteSpace(TableOfInformationJson))
        {
            return new DataTable();
        }
        return TableOfInformationJson.JsonDeserialize<DataTable>();
    }
    set { TableOfInformationJson = value.ToJson(); }
}

这里我有2个扩展方法如下:

public static string ToJson<T>(this T item)
{
    return JsonConvert.SerializeObject(item);
}

public static T JsonDeserialize<T>(this string json)
{
    return JsonConvert.DeserializeObject<T>(json);
}

【讨论】:

  • 非常感谢您。我知道从索引的角度来看,这并不理想,或者确保数据库中的所有数据都是可查询的。但是,我不知道一种简单且易于实现的方法来代替创建实际表。 DataTable 可以是任何维度(取决于用户,我事先不知道),并且可以在应用程序中更改维度大小。一个类也可以有多个表,我希望能够轻松管理它们。是否有理由让我更愿意考虑 JSON(它是否更独立于平台)?
  • @User_FSharp1123,我不确定您对尺寸大小的意思。至于 JSON 与 XML,实际上并没有太大的区别,只是 JSON 肯定会占用更少的空间。至于性能,老实说,我不能说序列化/反序列化 JSON 是否比使用 XML 更快。你可以在网上找到一些关于它的信息,或者制作某种控制台测试应用程序来进一步调查它。除此之外,我想这只是个人喜好问题。
  • 所以我所说的维度大小的意思是,我看不到如何遵循 Amadeus 指定的方法,因为它需要为 DataTable 中的每一列都有一个属性(行显然赢了不是问题)。但是,我不知道会有多少列(可能是 10 列,也可能是 100 列,这取决于用户),这就是为什么我认为您在此处提出的解决方案更有意义。我热衷于使用 XML 方法,因为它似乎很容易在 .NET 和 SQL 数据库中解析。
  • @User_FSharp1123,当然……如果是这样,请记住将其标记为答案。
【解决方案2】:

您可以创建一个包含 DataTable 中所有字段的模型。

public class PersonData
{
  public string Address { get; set;}
  public bool IsStackOverflowUser {get; set;}
  public int Age {get; set;}
} 

然后您可以将 PersonData 属性添加到您的 Person 模型

public class Person
{
  public string Name {get; set;}
  public PersonData PersonalInformation {get; set;}
}

【讨论】:

  • 因此,尽管这是理想的情况,但我不知道 DataTable 中的字段到那个程度。它们是动态创建的,因为它是一个包含双精度的二维数据结构,即可以是 10x4 或 20x6,或者任何情况。对于 Person 类的特定实例,尺寸也可以更改(例如,从 10x4 更改为 10x6)。
  • 重要的是还要注意它不仅包含双精度数(否则我会使用数组),而是包含字符串和双精度/整数值的组合。 Person 类将是层次结构的一部分(例如 Parent、GrandParent、Siblings),其中每个类可以包含多个 DataTable,不一定具有相同的维度。
  • 这听起来像是ExpandoObjects 的情况。您可以尝试将所有单元格内容解析为字符串,然后使用 Int32.TryParseDouble.TryParse 方法解析 DataTable 中的任何 int 或 double。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
相关资源
最近更新 更多