【发布时间】:2012-07-20 08:05:08
【问题描述】:
我已经看过this question,但它没有解释它,以便我了解实际发生的情况。我已经开发了多年,以前从未遇到过这种情况(尽管我最近才使用 Linq 和 Parallel)。
我的代码是:
Parallel.ForEach(databaseMetadata.Rows.Cast<DataRow>(), row => {
var fieldName = row.Item("Name", "");
var field = this.Fields.Where(f => f.Name.ToLower() == fieldName.ToLower()).SingleOrDefault();
if(field != null) { field.Validate(this, connection, row); }
});
在 field.Validate 函数中,它将字段对象上名为“HasBeenValidated”的属性设置为 true,但是,一旦我退出此 Parallel.ForEach 循环,该属性就会设置回 false。有人可以解释为什么会发生这种情况以及我可以做些什么来确保循环内的更改在循环外保持不变。
已编辑:
下面是field.Validate中的代码副本:
internal void Validate(EntityAttribute entity, SqlConnection connection, [AllowNull] DataRow metadata) {
this.HasBeenValidated = true;
var isRequired = this.IsRequired;
var maxLength = this.MaxLength;
var isAutoGenerated = this.IsAutoGenerated;
var dataType = this.member.PropertyType;
var dataTypeAsString = "";
if(metadata != null) {
isRequired = metadata.Item("IsRequired", false);
maxLength = metadata.Item("MaxLength", 0);
isAutoGenerated = metadata.Item("IsAutoGenerated", false);
dataTypeAsString = metadata.Item("DataType", "");
if(dataTypeAsString == this.member.PropertyType.ToSqlServerDataType()) { dataTypeAsString = ""; }
} else {
dataTypeAsString = this.member.PropertyType.ToSqlServerDataType();
}
if(metadata == null || isRequired != this.IsRequired || maxLength != this.MaxLength || isAutoGenerated != this.IsAutoGenerated || dataTypeAsString != "") {
var sql = string.Format((metadata == null ? "ALTER TABLE [{0}].[{1}] ADD" : "ALTER TABLE {0} ALTER COLUMN"), entity.Schema, entity.Name) + " " + this.Sql + ";";
if(!connection.ExecuteCommand(sql, 1)) {
throw new InvalidOperationException("Unable to create or alter column '" + this.Name + "' on table '" + entity.Name + "'.");
}
}
}
HasBeenValidated 属性在字段对象上定义为:
internal bool HasBeenValidated { get; set; }
提前致谢。
【问题讨论】:
-
我想这里没有值类型在起作用?显然除了 bool 属性。您是否尝试过将其更改为普通的
foreach并逐步执行? -
当我们看不到
Validate(...),看不到数据来自哪里(即它是可重复的列表?还是.Rows实际查询时,您要求我们发表评论)数据),看不到你在哪里检查HasBeenValidated(或它被设置的地方),也看不到这是struct与class的问题。我们可能假设DataRow表示这是DataTable,但即使这样的假设也是不合理的......此外,请注意DataTable并不声称对于写操作是线程安全的,尽管推测这是相关的。 -
aka:你有一个我们可以实际看到的可重复的例子吗?
-
@AdamHouldsworth 和 DarenThomas:我会将其更改为 for 循环,看看会发生什么。
-
@MarcGravell:我已经包含了验证代码。行实际上来自数据表。 HasBeenValidated 是 fields 对象上的一个简单属性,我已将其包含在问题的编辑中。这段代码中根本没有结构,它们都是类。我没有在此代码中将任何数据写入数据表,因此线程安全不是问题(无论如何都与数据表写入有关)。
标签: c# linq foreach parallel-processing persistence