C# 从数据库表中填充多维数组

Posted

技术标签:

【中文标题】C# 从数据库表中填充多维数组【英文标题】:C# Populate Multidimensional array from database table 【发布时间】:2022-01-11 07:00:25 【问题描述】:

我使用 EF Core 为我的博客创建了一个包含 7 列的数据库表,我正在尝试在我的 c# 代码中创建一个多维数组,以便在页面加载时我可以从数据库中检索值,然后将值分配到我的控制器到引导卡中的文本字段。所以 card.1 将有来自数据库中第 1 行的详细信息,卡 .2 将有来自数据库中第 2 行的详细信息等。

这是我的数据库模型:

public class ArticlesList

    [Key]
    public string ArticleReference  get; set; 
    public string TitleImageUrl  get; set; 
    public string UserId  get; set; 
    public string Title  get; set; 
    public string Snippet  get; set; 

    [DataType(DataType.DateTime)]
    [Column(TypeName = "datetime2")]
    public DateTime? PostedDateTime  get; set; 
    public bool WeeklyNewsList  get; set; 

这是我的数据库结构:

我正在尝试按照以下在我的控制器中将数据库中的值分配给我的 ViewModel。但要做到这一点,我需要获取 BOTH 行的数据。

在下面第一次尝试的控制器中,工作正常,它填充第一张卡没有错误:

string [,] articles = GetArticlesCardDetails.GetCardDetails();

var viewModel = new ArticlesViewModel
            
                Article1CardImage = articles[0, 1],
                Article1CardTitle = articles[0,3],
                Article1CardContent = articles[0, 4],
                Article1CardDate = articles[0, 5],

                Article2CardTitle = "",
                Article2CardContent = "",
                Article2CardDate = ""
 ;

但是这会引发 Index out of range 异常

string [,] articles = GetArticlesCardDetails.GetCardDetails();

var viewModel = new ArticlesViewModel
            
                Article1CardImage = articles[0, 1],
                Article1CardTitle = articles[0,3],
                Article1CardContent = articles[0, 4],
                Article1CardDate = articles[0, 5],

                Article2CardTitle = articles[1, 3],
                Article2CardContent = articles[1, 4],
                Article2CardDate = articles[1, 5]
 ;

以下是我尝试填充数组以便可以将其返回到我的控制器。 这似乎是出错的地方,它工作正常,但只是将第二个数据库行填充到我的数组中。我将每一列作为一个列表,然后尝试将这些值添加到一个数组中.我可以很好地添加和检索 [0,0] 到 [0,7] 的值,但是一旦我尝试检索 [1,0] [1,1] 等,它就会引发索引超出范围错误。

我整天都在研究这个,发现了很多关于 php 代码或原始 SQL 的信息。还有关于嵌套 for 循环的信息,但我试过了,但无法让它工作。对于本质上填充简单数组的内容来说,这似乎也非常复杂。有人还在 cmets 中建议我研究数据绑定,我确实这样做了。我最终可能需要它来动态更新 UI,但我现在不需要它。 现在我只需要从几行数据库数据创建一个简单的数组。

尝试 1

public class GetArticlesCardDetails

    private static readonly ApplicationDbContext _context = new();

    public static string[,] GetCardDetails()
    
        _context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        var articlesEntriesCount = _context.ArticlesList.Count();
        Debug.WriteLine("************** articlesEntriesCount: " + articlesEntriesCount.ToString());
        _context.ArticlesList.OrderByDescending(x => new  x.PostedDateTime );
        var Articles = _context.ArticlesList.FirstOrDefault();
        string[,] articles =  ;

        List<string> referenceList = _context.ArticlesList.Where(c => c.ArticleReference != null).Select(c => c.ArticleReference).ToList();
        List<string> titleImageUrlList = _context.ArticlesList.Where(c => c.TitleImageUrl != null).Select(c => c.TitleImageUrl).ToList();
        List<string> userIdList = _context.ArticlesList.Where(c => c.UserId != null).Select(c => c.UserId).ToList();
        List<string> titleList = _context.ArticlesList.Where(c => c.Title != null).Select(c => c.Title).ToList();
        List<string> snippetList = _context.ArticlesList.Where(c => c.Snippet != null).Select(c => c.Snippet).ToList();
        List<DateTime> postedList = _context.ArticlesList.Where(c => c.PostedDateTime != null).Select(c => c.PostedDateTime.Value).ToList();
        List<bool> weeklyBoolList = _context.ArticlesList.Select(c => c.WeeklyNewsList).ToList();

        for (int i = 0; i < articlesEntriesCount; i++)
        
            Debug.WriteLine("************** i: " + i.ToString());
                articles = new string[,]   referenceList[i], titleImageUrlList[i], userIdList[i], titleList[i], snippetList[i], postedList[i].ToString(), weeklyBoolList[i].ToString()  ;
        ;

        return articles;
    

下面是我尝试嵌套 for 循环: 尝试 2

   public class GetArticlesCardDetails
    
        private static readonly ApplicationDbContext _context = new();

        public static string[,] GetCardDetails()
        
            _context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
            var articlesEntriesCount = _context.ArticlesList.Count();
            Debug.WriteLine("************** articlesEntriesCount: " + articlesEntriesCount.ToString());
            _context.ArticlesList.OrderByDescending(x => new  x.PostedDateTime );
            var Articles = _context.ArticlesList.FirstOrDefault();
            string[,] articles =  ;

            List<string> referenceList = _context.ArticlesList.Where(c => c.ArticleReference != null).Select(c => c.ArticleReference).ToList();
            List<string> titleImageUrlList = _context.ArticlesList.Where(c => c.TitleImageUrl != null).Select(c => c.TitleImageUrl).ToList();
            List<string> userIdList = _context.ArticlesList.Where(c => c.UserId != null).Select(c => c.UserId).ToList();
            List<string> titleList = _context.ArticlesList.Where(c => c.Title != null).Select(c => c.Title).ToList();
            List<string> snippetList = _context.ArticlesList.Where(c => c.Snippet != null).Select(c => c.Snippet).ToList();
            List<DateTime> postedList = _context.ArticlesList.Where(c => c.PostedDateTime != null).Select(c => c.PostedDateTime.Value).ToList();
            List<bool> weeklyBoolList = _context.ArticlesList.Select(c => c.WeeklyNewsList).ToList();

            for (int i = 0; i < articlesEntriesCount; i++)
            
                for (int j = 0; j < articlesEntriesCount; j++)
                
                    for (int k = 0; k < articlesEntriesCount; k++)
                    
                        for (int l = 0; l < articlesEntriesCount; l++)
                        
                            for (int m = 0; m < articlesEntriesCount; m++)
                            
                                for (int n = 0; n < articlesEntriesCount; n++)
                                
                                    for (int o = 0; o < articlesEntriesCount; o++)
                                    
                                        Debug.WriteLine("************** i: " + i.ToString());
                                        articles = new string[,]   referenceList[i], titleImageUrlList[i], userIdList[i], titleList[i], snippetList[i], postedList[i].ToString(), weeklyBoolList[i].ToString() ;
                                    
                                
                            
                        
                    
                
            ;

            return articles;
        
    

尝试在 cmets 中简单地使用下面建议的列表会在返回时引发隐式转换错误:

尝试 3

public class GetArticlesCardDetails

    private static readonly ApplicationDbContext _context = new();

    public static List<object> GetCardDetails()
    
        _context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        var articlesEntriesCount = _context.ArticlesList.Count();
        var articles = _context.ArticlesList.ToList();

        return articles;
    

在上面第三个选项的控制器中:

    List<object> articles = GetArticlesCardDetails.GetCardDetails();

我做错了什么? 如何创建一个数组并从我的数据库中填充它,以便随后检索相关值?

【问题讨论】:

抛弃多维数组。 (我假设这是基于 EF 的(对您的问题有用的信息,顺便说一句)并且 _contextDbContext。)而不是使用 FirstOrDefault,请尝试 var myData = _context.ArticlesList.ToList(); 并查看 myData在调试器中 这会为 myData 生成什么类型​​?它不是 List,因为 List 引发了一个隐式转换错误,即 Generic.List 无法转换为 string[ , ] 它应该是任何ArticlesList 映射到该表的列表(可能是List&lt;ArticlesList&gt; - 从您的代码中无法分辨)。不要尝试使用多维数组,使用该列表和 ArticlesList 类型的属性(或该列表的任何通用参数)。使用调试器来解决这个问题——我们不能从这里做到这一点 调用_context.ArticlesList.ToList() 将为您提供查询结果的强类型列表,每行中的字段具有强类型(并正确命名)属性。使用该信息。您可以将数据绑定到该列表。不要通过将其转换为List&lt;object&gt; 来丢失这些信息。找到一些实体框架示例,我已经用尽了我可以通过电话告诉你的内容。 添加了更多细节@AntiqTech 【参考方案1】:

根据对原始答案的评论中的建议,感谢Good Night Nerd Pride,在完成了 EF 教程后,我现在进一步改进了这一点。

在我的控制器中,我只有:

            var viewModel = new ArticlesViewModel
            
             //some static variables are assigned in here...
            ;

            viewModel.ListOfArticles = _context.ArticlesList;

在我看来,我正在根据suggested tutorial 动态生成和填充元素。

【讨论】:

【参考方案2】:

知道了!结果我需要一个 DataTable,而不是数组。我正在使用 SQL 查询填充 DataTable,并且它运行良好。以下是其他人在未来遇到类似问题的情况:

在我的控制器中:

            DataTable articles = _context.DataTable("SELECT * FROM [dbo].[ArticlesList]", new SqlParameter("paramName", SqlDbType.NVarChar)  Value = "a" 

            var viewModel = new ArticlesViewModel
            
                Article1CardImage = articles.Rows[0].Field<string>(1),
                Article1CardTitle = articles.Rows[0].Field<string>(3),
                Article1CardContent = articles.Rows[0].Field<string>(4),
                Article1CardDate = articles.Rows[0].Field<DateTime>(5).ToString(),

                Article2CardTitle = articles.Rows[1].Field<string>(3),
                Article2CardContent = articles.Rows[1].Field<string>(4),
                Article2CardDate = articles.Rows[1].Field<DateTime>(5).ToString(),
;

还有我的 GetArticlesCardDetails 类:

public static class GetArticlesCardDetails

    public static DataTable DataTable(this ApplicationDbContext _context, string sqlQuery, params DbParameter[] parameters)
    
        _context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        DataTable dataTable = new DataTable();
        DbConnection connection = _context.Database.GetDbConnection();
        DbProviderFactory dbFactory = DbProviderFactories.GetFactory(connection);

        using (var cmd = dbFactory.CreateCommand())
        
            cmd.Connection = connection;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sqlQuery;

            if (parameters != null)
            
                foreach (var item in parameters)
                
                    cmd.Parameters.Add(item);
                
            
            using (DbDataAdapter adapter = dbFactory.CreateDataAdapter())
            
                adapter.SelectCommand = cmd;
                adapter.Fill(dataTable);
            
        

        //Debug.WriteLine("************** dataTable: " + string.Join(Environment.NewLine, dataTable.Rows.OfType<DataRow>().Select(x => string.Join(" ; ", x.ItemArray))));
        return dataTable;
    

还有来自here 的一点帮助。

【讨论】:

恭喜您找到解决问题的方法!但是,我强烈建议您花时间研究实体框架的教程(例如this one)。相信我们,它会在以后为您省去很多麻烦:) 感谢@GoodNightNerdPride,我完成了本教程,并针对上述问题发布了更好的答案。非常感谢。

以上是关于C# 从数据库表中填充多维数组的主要内容,如果未能解决你的问题,请参考以下文章

将多维数组从mysql层次结构表填充到php

在vba中从查询填充数组然后将数据插入表中

C#如何读取数据库表中每一列的数据分别赋值给数组

如何(如果可能)从 VBA Excel 2010 的工作表中定义和填充全局数组变量?

我想在我的表中获取多维数组

从数组填充 Bootstrap 4 表?