如何使用Linq2Sql将多个数据库列存储到数组中

时间:2010-01-07 12:31:09

标签: c# sql-server linq-to-sql c#-3.0

我必须使用通常如下所示的多个SQL Server表:

int id_this, int id_that, ..., double Value1, double Value2, ..., double Value96

我知道这很糟糕,但我无法改变它。我现在要做的是定义一些像

这样的类
public class Foo
{
    public int Id_This { get; set; }
    public int Id_That { get; set; }
    ...
    public double Value[];
}

Value-Array当然是属性,但我认为你明白了。

问题是,如何尽可能轻松地将96列放入数组中。

我可以使用普通的SqlDataReader,因为DataRow允许索引访问,但我想知道我是否可以声明一些属性或编写一些最少量的代码来直接使用LINQ2SQL类。

至少,我想做

dataContext.ExecuteQuery<Foo>("SELECT * FROM Foo");

1 个答案:

答案 0 :(得分:2)

是的,那......好吗? DataContext方法总是期望实体类型;没有ExecuteReader,这是一种痛苦(但可以理解,因为它想表现为ORM)。老实说,我很想使用ADO.NET来对抗这个表,但是如果你已经将宽表映射到DataContext,你应该可以使用常规的C#或反射。

由于这个数字没有变化,除非你有多个表,否则我会咬紧牙关写一些丑陋的代码:

Foo foo = new Foo { Id_This = obj.Id_This, Id_That = obj.Id_That,
    Values = new double[] {obj.Value1, obj.Value2, ... } };

如果您有多个表...反射,可能通过Expression进行优化:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
class FooUgly
{
    public int IdThis { get; set; }
    public int IdThat { get; set; }
    public double Value1 { get; set; }
    public double Value2 { get; set; }
    public double Value3 { get; set; }
}
class Foo
{
    public int IdThis { get; set; }
    public int IdThat { get; set; }
    public double[] Values { get; set; }
    public Foo() { }
    internal Foo(FooUgly ugly)
    {
        IdThis = ugly.IdThis;
        IdThat = ugly.IdThat;
        Values = extractor(ugly);
    }
    // re-use this!!!
    static readonly Func<FooUgly, double[]> extractor =
        ValueExtractor<FooUgly, double>.Create("Value", 1, 3);
}
static class Program
{
    static void Main()
    {
        FooUgly ugly = new FooUgly { IdThis = 1, IdThat = 2, Value1 = 3, Value2 = 4, Value3 = 5 };
        Foo foo = new Foo(ugly);
    }
}
static class ValueExtractor<TFrom,TValue>
{
    public static Func<TFrom, TValue[]> Create(string memberPrefix, int start, int end)
    {
        if(end < start) throw new ArgumentOutOfRangeException();
        ParameterExpression param = Expression.Parameter(typeof(TFrom), "source");
        List<Expression> vals = new List<Expression>();
        for(int i = start ; i <= end ; i++) {
            vals.Add(Expression.PropertyOrField(param, memberPrefix + i));
        }
        Expression arr = Expression.NewArrayInit(typeof(TValue), vals);
        return Expression.Lambda<Func<TFrom, TValue[]>>(arr, param).Compile();
    }
}