如何使用Entity Framework Code-First方法将double []数组存储到数据库

时间:2013-03-05 10:03:21

标签: c# .net entity-framework ef-code-first fluent-interface

如何使用Entity Framework Code-First将数组的双精度数据存储到数据库,而不影响现有代码和架构设计?

我查看了Data Annotation和Fluent API,我还考虑将double数组转换为字节字符串,并将该字节存储到自己的列中的数据库中。

我无法使用Fluent API访问public double[] Data { get; set; }属性,我得到的错误消息是:

  

类型double[]必须是不可为空的值类型才能使用   它作为参数'T'。

存储Data的类成功存储在数据库中,以及与此类的关系。我只缺少Data列。

8 个答案:

答案 0 :(得分:42)

你可以这样做:

    [NotMapped]
    public double[] Data
    {
        get
        {
            string[] tab = this.InternalData.Split(',');
            return new double[] { double.Parse(tab[0]), double.Parse(tab[1]) };
        }
        set
        {
            this.InternalData = string.Format("{0},{1}", value[0], value[1]);
        }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public string InternalData { get; set; }

答案 1 :(得分:24)

感谢大家的投入,由于您的帮助,我能够找到解决此问题的最佳方法。这是:

 public string InternalData { get; set; }
 public double[] Data
 {
    get
    {
        return Array.ConvertAll(InternalData.Split(';'), Double.Parse);                
    }
    set
    {
        _data = value;
        InternalData = String.Join(";", _data.Select(p => p.ToString()).ToArray());
    }
 }

感谢这些stackoverflow帖子: String to Doubles arrayArray of Doubles to a String

答案 2 :(得分:5)

我知道它有点贵,但你可以这样做

class Primitive
{
    public int PrimitiveId { get; set; }
    public double Data { get; set; }

    [Required]
    public Reference ReferenceClass { get; set; }
}

// This is the class that requires an array of doubles
class Reference
{
    // Other EF stuff

    // EF-acceptable reference to an 'array' of doubles
    public virtual List<Primitive> Data { get; set; }
}

现在,这将把单个实体(此处为'Reference')映射到Primitive类的'list'。这基本上是为了让SQL数据库感到高兴,并允许您适当地使用您的数据列表。

这可能不适合您的需求,但会让EF感到高兴。

答案 3 :(得分:4)

如果您使用List<double>而不是double[],那将会容易得多。您已经有一个存储Data值的表格。您可能从某个表到存储双值的表中有外键。创建另一个反映存储双精度表的模型,并在映射类中添加外键映射。这样,您就不需要添加一些复杂的后台逻辑来检索或存储类属性中的值。

答案 4 :(得分:1)

内森怀特有最好的答案(得到我的投票)。

这是对Joffrey Kern的答案的一个小改进,允许任何长度的列表(未经测试):

    [NotMapped]
    public IEnumerable<double> Data
    {
        get
        {
            var tab = InternalData.Split(',');
            return tab.Select(double.Parse).AsEnumerable();
        }
        set { InternalData = string.Join(",", value); }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public string InternalData { get; set; }

答案 5 :(得分:1)

不要使用双[]使用List insted。

喜欢这个。

public class MyModel{
    ...
    public List<MyClass> Data { get; set; }
    ...
}

public class MyClass{
    public int Id { get; set; }
    public double Value { get; set; }
}

我看到的所有解决方案都很糟糕,因为:

  1. 如果您创建表格,则不希望存储如下数据:&#34; 99.5,89.65,78.5,15.5&#34;那是无效的!首先它是一个字符串,意味着你可以在其中输入字母,当你的ASP.NET服务器调用double.Parse它将导致FormatException并且你真的不想要!

  2. 速度较慢,因为您的服务器必须解析字符串。为什么要解析字符串而不是从SQL Server中获取几乎准备好的数据?

答案 6 :(得分:1)

如果您的集合可以是 null,并且您希望保留它,请执行以下操作:

[NotMapped]
public double[] Data
{
    get => InternalData != null ? Array.ConvertAll(Data.Split(';'), double.Parse) : null;
    set => InternalData = value != null ? string.Join(";", value) : null;
}

此外,在字符串属性上指定 [Column(TypeName = "varchar")] 以获得更高效的存储数据类型。

答案 7 :(得分:0)

@Jonas's 答案的完美改进是添加必要的注释。所以,一个更干净的版本是

[EditorBrowsable(EditorBrowsableState.Never)]
[JsonIgnore]
public string InternalData { get; set; }

[NotMapped]
public double[] Data
{
    get => Array.ConvertAll(InternalData.Split(';'), double.Parse);
    set 
    {
        InternalData = string.Join(";", value.Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray());
    }
}

[JsonIgnore] 注释将忽略来自 JSON 序列化和 Swagger UI 的 InternalData 字段。

[EditorBrowsable(EditorBrowsableState.Never)] 将从 IDE 智能感知中隐藏公共方法