【问题标题】:Why does iterating over IQueryable give the first value for each item in the result?为什么迭代 IQueryable 会为结果中的每个项目提供第一个值?
【发布时间】:2013-03-26 20:33:31
【问题描述】:

我有一段代码尝试从数据库中查询一些简单的配置参数。但是,使用下面的代码,只要我枚举结果,我就会得到结果中每个项目的第一个值:

var db = new ConfigurationServiceDataContext("Server=vsdcs022.aridev.lcl;Database=ConfigurationService;Trusted_Connection=True;");

var parameters =
    from configContents in db.ConfigurationContents
    where
        configContents.ConfigurationContextsTable.ConfigurationContextName == contextName &&
        configContents.ConfigurationSectionTable.ConfigurationSectionName == sectionName
    select configContents;

// print stuff for debugging purposes:
foreach (var parameter in parameters)
{
    Console.WriteLine("key = '{0}', value = '{1}'", parameter.ConfigurationKey, parameter.ConfigurationValue);
}

return parameters.ToDictionary(parameter => parameter.ConfigurationKey, parameter => parameter.ConfigurationValue);

如果我打印结果(在尝试将它们添加到新字典之前),我会得到如下信息:

key = 'key1', value = 'value1'
key = 'key1', value = 'value1'
key = 'key1', value = 'value1'

但是如果我用匿名类型替换 select 行,它就可以正常工作:

    select new { configContents.ConfigurationKey, configContents.ConfigurationValue };

使用这种匿名类型,我得到以下结果:

key = 'key1', value = 'value1'
key = 'key2', value = 'value2'
key = 'key3', value = 'value3'

我已经研究了几个小时,但无济于事,虽然我可以用匿名类型说它很好,但这真的让我很困扰。我已经看到很多例子表明我的第一个代码块应该可以正常工作。我确定我在做一些傻事,我只是看不到它!

有什么想法吗?

以下是我使用的模型的全部细节,从 DataContext 实现开始:

using System.Data.Linq;
using Ari.Core.ConfigurationService.LinqEntityClasses;

namespace Ari.Core.ConfigurationService
{
    class ConfigurationServiceDataContext : DataContext
    {
        public Table<ConfigurationContentsTable> ConfigurationContents;
        public Table<ConfigurationContextsTable> ConfigurationContexts;
        public Table<ConfigurationSectionsTable> ConfigurationSections;

        public ConfigurationServiceDataContext(string connectionString) : base(connectionString) {}
    }
}

核心内容表由我的 ConfigurationContentsTable 实体类表示:

using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace Ari.Core.ConfigurationService.LinqEntityClasses
{
    [Table(Name = "ConfigurationContents")]
    class ConfigurationContentsTable
    {
        private long _configurationContextId;
        private string _configurationKey;
        private string _configurationValue;
        private EntityRef<ConfigurationContextsTable> _configurationContextsTable;
        private EntityRef<ConfigurationSectionsTable> _configurationSectionsTable;

        public ConfigurationContentsTable()
        {
            _configurationContextsTable = new EntityRef<ConfigurationContextsTable>();
            _configurationSectionsTable = new EntityRef<ConfigurationSectionsTable>();
        }

        [Column(Storage = "_configurationContextId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true,
            IsDbGenerated = true)]
        public long ConfigurationContextId
        {
            get { return _configurationContextId; }
        }

        [Column(Storage = "_configurationKey")]
        public string ConfigurationKey
        {
            get { return _configurationKey; }
            set { _configurationKey = value; }
        }

        [Column(Storage = "_configurationValue")]
        public string ConfigurationValue
        {
            get { return _configurationValue; }
            set { _configurationValue = value; }
        }

        [Association(Storage = "_configurationContextsTable", OtherKey = "ConfigurationContextId")]
        public ConfigurationContextsTable ConfigurationContextsTable
        {
            get { return _configurationContextsTable.Entity; }
            set { _configurationContextsTable.Entity = value; }
        }

        [Association(Storage = "_configurationSectionsTable", OtherKey = "ConfigurationSectionId")]
        public ConfigurationSectionsTable ConfigurationSectionTable
        {
            get { return _configurationSectionsTable.Entity; }
            set { _configurationSectionsTable.Entity = value; }
        }
    }
}

这两个关联表非常简单,仅用于规范化目的。它们表示如下:

using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace Ari.Core.ConfigurationService.LinqEntityClasses
{
    [Table(Name = "ConfigurationContexts")]
    class ConfigurationContextsTable
    {
        private long _configurationContextId;
        private string _configurationContextName;
        private EntityRef<ConfigurationContentsTable> _configurationContentsTable;

        public ConfigurationContextsTable()
        {
            _configurationContentsTable = new EntityRef<ConfigurationContentsTable>();
        }

        [Column(Storage = "_configurationContextId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true,
            IsDbGenerated = true)]
        public long ConfigurationContextId
        {
            get { return _configurationContextId; }
        }

        [Column(Storage = "_configurationContextName")]
        public string ConfigurationContextName
        {
            get { return _configurationContextName; }
            set { _configurationContextName = value; }
        }

        [Association(Storage = "_configurationContentsTable", ThisKey = "ConfigurationContextId")]
        public ConfigurationContentsTable ConfigurationContentsTable
        {
            get { return _configurationContentsTable.Entity; }
            set { _configurationContentsTable.Entity = value; }
        }
    }
}

最后:

using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace Ari.Core.ConfigurationService.LinqEntityClasses
{
    [Table(Name = "ConfigurationSections")]
    class ConfigurationSectionsTable
    {
        private long _configurationSectionId;
        private string _configurationSectionName;
        private EntityRef<ConfigurationContentsTable> _configurationContentsTable;

        public ConfigurationSectionsTable()
        {
            _configurationContentsTable = new EntityRef<ConfigurationContentsTable>();
        }

        [Column(Storage = "_configurationSectionId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true,
            IsDbGenerated = true)]
        public long ConfigurationSectionId
        {
            get { return _configurationSectionId; }
        }

        [Column(Storage = "_configurationSectionName")]
        public string ConfigurationSectionName
        {
            get { return _configurationSectionName; }
            set { _configurationSectionName = value; }
        }

        [Association(Storage = "_configurationContentsTable", ThisKey = "ConfigurationSectionId")]
        public ConfigurationContentsTable ConfigurationContentsTable
        {
            get { return _configurationContentsTable.Entity; }
            set { _configurationContentsTable.Entity = value; }
        }
    }
}

【问题讨论】:

  • 好问题!请发布您的“打印结果”代码(您的代码看起来不错,目前我怀疑您正在访问打印代码中修改后的闭包)
  • 你能发布打印(不正确)结果的代码吗?
  • 闻起来像修改过的封口。
  • 我已将用于枚举/打印值的逻辑添加到第一个代码块。
  • @Jason,问题在我帖子的第二句中描述。然后我继续通过示例详细说明问题。不确定你在说什么。谢谢。

标签: c# .net linq-to-sql


【解决方案1】:

因此,在对我的代码进行更多挖掘和审查之后,我发现了两个问题,在纠正后会产生预期的结果。

首先,在我的 ConfigurationContentsTable 实体类中,我的 PK 字段被配置为查看 ConfigurationContextId 而不是 ConfigurationContentId 字段。当我解决这个问题时,当我期望三个结果时,我开始只得到一个结果。这使我查看了表关联/连接逻辑(请参阅下面的第二项)。更正 ConfigurationContentsTable 中的代码 sn-p:

[Column(Storage = "_configurationContentId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
public long ConfigurationContentId
{
    get { return _configurationContentId; }
}

其次,对于所有具有 [Association(Storage = ...] 属性的 EntityRef 属性,我将 ThisKeyOtherKey 属性颠倒了。一旦我将 ConfigurationContentsTable 更改为使用 ThisKey 并将 ConfigurationContextsTable 和 ConfigurationSectionsTable 更改为使用 OtherKey,我开始看到预期的三个不同的结果。

ConfigurationContentsTable 的更正代码:

[Association(Storage = "_configurationContextsTable", ThisKey = "ConfigurationContextId")]
public ConfigurationContextsTable ConfigurationContextsTable
{
    get { return _configurationContextsTable.Entity; }
    set { _configurationContextsTable.Entity = value; }
}

[Association(Storage = "_configurationSectionsTable", ThisKey = "ConfigurationSectionId")]
public ConfigurationSectionsTable ConfigurationSectionsTable
{
    get { return _configurationSectionsTable.Entity; }
    set { _configurationSectionsTable.Entity = value; }
}

ConfigurationContextsTable 的更正代码:

[Association(Storage = "_configurationContentsTable", OtherKey = "ConfigurationContextId")]
public ConfigurationContentsTable ConfigurationContentsTable
{
    get { return _configurationContentsTable.Entity; }
    set { _configurationContentsTable.Entity = value; }
}

最后,更正了 ConfigurationSectionsTable 的代码:

[Association(Storage = "_configurationContentsTable", OtherKey = "ConfigurationSectionId")]
public ConfigurationContentsTable ConfigurationContentsTable
{
    get { return _configurationContentsTable.Entity; }
    set { _configurationContentsTable.Entity = value; }
}

【讨论】:

  • 我遇到了这个问题,因为我手动创建了我的 Linq 实体类。如果我只是添加了一个“LINQ to SQL 类”项,它会创建一个 dbml 设计界面,您可以在该界面上拖动您的数据库连接(从服务器资源管理器),我会完全避免这个问题。这样做会自动为您生成所有实体类。
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
  • 1970-01-01
相关资源
最近更新 更多