Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将.NET数据表传递给MATLAB_C#_Matlab_Ado.net_Matlab Deployment - Fatal编程技术网

C# 将.NET数据表传递给MATLAB

C# 将.NET数据表传递给MATLAB,c#,matlab,ado.net,matlab-deployment,C#,Matlab,Ado.net,Matlab Deployment,我正在为一个Matlab组件构建一个接口层,该组件用于分析由我正在构建的一个单独的.NET应用程序维护的数据。我试图将.NET数据表序列化为一个数字数组,以传递给MATLAB组件(作为更通用的序列化例程的一部分) 到目前为止,我在传递数字数据表方面相当成功,但在尝试添加数据类型为DateTime的列时遇到了障碍。到目前为止,我一直在做的是将DataTable中的值填充到一个双精度数组中,因为MATLAB实际上只关心双精度,然后直接转换到MWNumericArray,它本质上是一个矩阵 这是当前的

我正在为一个Matlab组件构建一个接口层,该组件用于分析由我正在构建的一个单独的.NET应用程序维护的数据。我试图将.NET数据表序列化为一个数字数组,以传递给MATLAB组件(作为更通用的序列化例程的一部分)

到目前为止,我在传递数字数据表方面相当成功,但在尝试添加数据类型为
DateTime
的列时遇到了障碍。到目前为止,我一直在做的是将
DataTable
中的值填充到一个双精度数组中,因为MATLAB实际上只关心双精度,然后直接转换到
MWNumericArray
,它本质上是一个矩阵

这是当前的代码

else if (sourceType == typeof(DataTable))
{
    DataTable dtSource = source as DataTable;
    var rowIdentifiers = new string[dtSource.Rows.Count];               
    // I know this looks silly but we need the index of each item
    // in the string array as the actual value in the array as well
    for (int i = 0; i < dtSource.Rows.Count; i++)
    {
        rowIdentifiers[i] = i.ToString();
    }
    // convenience vars
    int rowCount = dtSource.Rows.Count;
    int colCount = dtSource.Columns.Count;
    double[,] values = new double[rowCount, colCount];

    // For each row 
    for (int rownum = 0; rownum < rowCount; rownum++)
    {
        // for each column
        for (int colnum = 0; colnum < colCount; colnum++)
        {
            // ASSUMPTION. value is a double
            values[rownum, colnum] = Conversion.ConvertToDouble(dtSource.Rows[rownum][colnum]);
        }
    }
    return (MWNumericArray)values;
}
但是正如我所说的,我得到了一个编译错误,同样是向构造函数传递一个对象数组

如果我错过了任何愚蠢的事情,我道歉。我用谷歌搜索了一下,但是关于Matlab到.NET接口的信息似乎有点浅薄,所以我把它贴在这里

提前谢谢

[编辑]

谢谢大家的建议

事实证明,对于我们的具体实现来说,最快、最有效的方法是在SQL代码中将Datetime转换为int

然而,在其他方法中,我建议使用MWCharArray方法。它使用了最少的麻烦,结果证明我只是做错了——你不能把它当作另一种MWArray类型来对待,因为它当然是设计用来处理多个数据类型的,你需要迭代它,坚持使用MWARRIAL或任何你喜欢的方法。需要注意的一点是,阵列是基于1的,而不是基于0的。那一个一直在吸引我


今天晚些时候我有时间的时候会进行更详细的讨论,但现在我没有。再次感谢大家的帮助。

一种选择是直接从matlab打开.NET代码,让matlab使用.NET接口直接查询数据库,而不是尝试执行您描述的序列化过程。我在我们的环境中多次这样做,并取得了巨大成功。在这样的努力中
Net.addAssembly
是你最大的朋友

详情在这里。

第二种选择是使用Matlab单元阵列。您可以对其进行设置,使列具有不同的数据类型,每列构成一个单元格。这是matlab本身在textscan函数中使用的技巧。我建议在此处阅读该函数的文档:


第三种选择是完全使用文本扫描。从.net代码中写出一个文本文件,并让textscan处理它的解析。Textscan是将此类数据输入matlab的非常强大的机制。您可以将textscan指向一个文件或一组字符串。

一个选项是直接从matlab打开.NET代码,让matlab使用.NET接口直接查询数据库,而不是尝试执行您描述的序列化过程。我在我们的环境中多次这样做,并取得了巨大成功。在这样的努力中
Net.addAssembly
是你最大的朋友

详情在这里。

第二种选择是使用Matlab单元阵列。您可以对其进行设置,使列具有不同的数据类型,每列构成一个单元格。这是matlab本身在textscan函数中使用的技巧。我建议在此处阅读该函数的文档:

第三种选择是完全使用文本扫描。从.net代码中写出一个文本文件,并让textscan处理它的解析。Textscan是将此类数据输入matlab的非常强大的机制。您可以将textscan指向一个文件或一组字符串。

正如注释中所建议的,如果要存储不同的数据类型(数字、字符串、结构等),则应使用此托管API公开的等效单元格数组,即类

为了举例说明,我实现了一个简单的.NET程序集。它公开了一个MATLAB函数,该函数接收单元格数组(来自数据库表的记录),并简单地打印它们。该函数将从我们的C#应用程序中调用,该应用程序生成一个示例
数据表
,并将其转换为一个
数组
(逐个单元格填充表格条目)

诀窍是将
DataTable
中包含的对象映射到
MWArray
派生类支持的类型。以下是我使用的(查看完整列表):

关于日期/时间数据的注释:在.NET中,日期和时间表示为:

自1月份以来经过的100纳秒间隔数 0001在00:00:00.000

在MATLAB中,函数必须这样说:

序列日期编号表示数据的整数和小数 从特定日期和时间算起的天数,其中datenum('Jan-1-0000 00:00:00')返回数字1

出于这个原因,我在C#应用程序中编写了两个助手函数来转换
DateTime
“ticks”以匹配MATLAB对序列日期号的定义


首先,考虑这个简单的MATLAB函数。它希望通过numCols接收包含表数据的numRos。在我的示例中,列是:Name(string)、Price(double)、Date(DateTime)

使用MatlabBuilder NE,我们将上述内容构建为.NET程序集。接下来,我们创建一个C#console应用程序,然后在上面生成的程序集之外,添加对
MWArray.dll
程序集的引用。这是我正在使用的程序:

using System;
using System.Data;
using MathWorks.MATLAB.NET.Utility;  // MWArray.dll
using MathWorks.MATLAB.NET.Arrays;   // MWArray.dll
using CellExample;                   // CellExample.dll assembly created

namespace CellExampleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // get data table
            DataTable table = getData();

            // create the MWCellArray
            int numRows = table.Rows.Count;
            int numCols = table.Columns.Count;
            MWCellArray cell = new MWCellArray(numRows, numCols);   // one-based indices

            // fill it cell-by-cell
            for (int r = 0; r < numRows; r++)
            {
                for (int c = 0; c < numCols; c++)
                {
                    // fill based on type
                    Type t = table.Columns[c].DataType;
                    if (t == typeof(DateTime))
                    {
                        //cell[r+1,c+1] = new MWNumericArray( convertToMATLABDateNum((DateTime)table.Rows[r][c]) );
                        cell[r + 1, c + 1] = convertToMATLABDateNum((DateTime)table.Rows[r][c]);
                    }
                    else if (t == typeof(string))
                    {
                        //cell[r+1,c+1] = new MWCharArray( (string)table.Rows[r][c] );
                        cell[r + 1, c + 1] = (string)table.Rows[r][c];
                    }
                    else
                    {
                        //cell[r+1,c+1] = new MWNumericArray( (double)table.Rows[r][c] );
                        cell[r + 1, c + 1] = (double)table.Rows[r][c];
                    }
                }
            }

            // call MATLAB function
            CellClass obj = new CellClass();
            obj.my_cell_function(cell);

            // Wait for user to exit application
            Console.ReadKey();
        }

        // DateTime <-> datenum helper functions
        static double convertToMATLABDateNum(DateTime dt)
        {
            return (double)dt.AddYears(1).AddDays(1).Ticks / (10000000L * 3600L * 24L);
        }
        static DateTime convertFromMATLABDateNum(double datenum)
        {
            DateTime dt = new DateTime((long)(datenum * (10000000L * 3600L * 24L)));
            return dt.AddYears(-1).AddDays(-1);
        }

        // return DataTable data
        static DataTable getData()
        {
            DataTable table = new DataTable();
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("Price", typeof(double));
            table.Columns.Add("Date", typeof(DateTime));

            table.Rows.Add("Amro", 25, DateTime.Now);
            table.Rows.Add("Bob", 10, DateTime.Now.AddDays(1));
            table.Rows.Add("Alice", 50, DateTime.Now.AddDays(2));

            return table;
        }
    }
}
正如注释中所建议的,如果要存储不同的数据类型(数字、字符串、结构等),则应使用此托管API公开的等效单元数组,即类

为了举例说明,我实现了一个简单的.NET程序集。它公开了一个MATLAB函数,该函数接收单元格数组(从数据库中记录)
.NET native type          MWArray classes
------------------------------------------
double,float,int,..       MWNumericArray
string                    MWCharArray
DateTime                  MWNumericArray       (using Ticks property)
function [] = my_cell_function(C)
    names = C(:,1);
    price = cell2mat(C(:,2));
    dt = datevec( cell2mat(C(:,3)) );

    disp(names)
    disp(price)
    disp(dt)
end
using System;
using System.Data;
using MathWorks.MATLAB.NET.Utility;  // MWArray.dll
using MathWorks.MATLAB.NET.Arrays;   // MWArray.dll
using CellExample;                   // CellExample.dll assembly created

namespace CellExampleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // get data table
            DataTable table = getData();

            // create the MWCellArray
            int numRows = table.Rows.Count;
            int numCols = table.Columns.Count;
            MWCellArray cell = new MWCellArray(numRows, numCols);   // one-based indices

            // fill it cell-by-cell
            for (int r = 0; r < numRows; r++)
            {
                for (int c = 0; c < numCols; c++)
                {
                    // fill based on type
                    Type t = table.Columns[c].DataType;
                    if (t == typeof(DateTime))
                    {
                        //cell[r+1,c+1] = new MWNumericArray( convertToMATLABDateNum((DateTime)table.Rows[r][c]) );
                        cell[r + 1, c + 1] = convertToMATLABDateNum((DateTime)table.Rows[r][c]);
                    }
                    else if (t == typeof(string))
                    {
                        //cell[r+1,c+1] = new MWCharArray( (string)table.Rows[r][c] );
                        cell[r + 1, c + 1] = (string)table.Rows[r][c];
                    }
                    else
                    {
                        //cell[r+1,c+1] = new MWNumericArray( (double)table.Rows[r][c] );
                        cell[r + 1, c + 1] = (double)table.Rows[r][c];
                    }
                }
            }

            // call MATLAB function
            CellClass obj = new CellClass();
            obj.my_cell_function(cell);

            // Wait for user to exit application
            Console.ReadKey();
        }

        // DateTime <-> datenum helper functions
        static double convertToMATLABDateNum(DateTime dt)
        {
            return (double)dt.AddYears(1).AddDays(1).Ticks / (10000000L * 3600L * 24L);
        }
        static DateTime convertFromMATLABDateNum(double datenum)
        {
            DateTime dt = new DateTime((long)(datenum * (10000000L * 3600L * 24L)));
            return dt.AddYears(-1).AddDays(-1);
        }

        // return DataTable data
        static DataTable getData()
        {
            DataTable table = new DataTable();
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("Price", typeof(double));
            table.Columns.Add("Date", typeof(DateTime));

            table.Rows.Add("Amro", 25, DateTime.Now);
            table.Rows.Add("Bob", 10, DateTime.Now.AddDays(1));
            table.Rows.Add("Alice", 50, DateTime.Now.AddDays(2));

            return table;
        }
    }
}
'Amro'
'Bob'
'Alice'

25
10
50

     2011            9           26           20           13       8.3906
     2011            9           27           20           13       8.3906
     2011            9           28           20           13       8.3906
DateTime dt = new DateTime(2014, 1, 1, 0, 0, 0);
double dtmat = convertToMATLABDateNum(dt);
datestr(datenum(735599.0))
ans = 31-Dec-2013