我有一些代码用于将数据行复制到您提供的对象中。数据行是弱类型的。现在,我可以使用反射将数据行中的所有数据分配给对象以获取属性,迭代这些属性并使用数据行设置它们的值。虽然这有效,但只有当底层数据类型相同(不是那么大的交易)时才有效,更重要的是,只要属性和字段的顺序相同。
这个问题有一个警告。大约90%的列名称与属性名称匹配。这是我被挂断的地方。示例:在我返回数据行的数据库中有一个名为Date_Created的字段,我的对象的属性在数据库中称为Created_Date或Modified_By,在object属性中称为Update_By。 (我无法重命名属性或表格,因此简单的答案是不可能的。)
我尝试这样做的原因是因为我的公司代码从数据库获取数据返回弱类型数据集,当我们更新或向数据库添加数据时,我们必须填充自定义类并将其传递给更新过程
我有什么方法可以比较datarow列并与object属性进行比较,或者在运行时将新的列名分配给datarow?
private static T CopyRecord<T>(DataRow record, dynamic newRecord)
{
//Get Properties
var properties = newRecord.GetType().GetProperties();
var column = 0;
foreach (PropertyInfo property in properties)
{
//If property is generic list, continue
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) continue;
//Check for dbnull, return null if true, or convert to correct type
var columnValue = Convert.IsDBNull(record[column]) ? null : Convert.ChangeType(record[column], Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType);
//Set property for newRecord
property.SetValue(newRecord, columnValue);
column++;
}
return newRecord;
}
编辑:在这种情况下使用自定义属性会起作用吗?我可以使用等效的数据库列名称为我的类属性添加前缀。这样,我可以在自定义类和弱类型数据行上使用反射并匹配所有数据。
答案 0 :(得分:2)
注意:不要像你在这里一样使用位置参考!它要求讨厌的错误。除非当然,否则其他人会维护这段代码并且你计划在那时退出(这就是我正在考虑继承的代码所发生的事情)。
将属性放在属性上。阅读这些。
如果您无法控制通用对象,但方法可以覆盖,则从中继承。
如果你不能这样做(或者这可能更容易),请将地图作为字典传递。现在,如果不传递额外的参数并锤击调用者,这很难实现。继承对象并让它们实现返回地图的接口(或者如果您可以直接编辑原始对象)。
此接口上的方法的实现(在您的特定对象中)将返回一个字典,它将包含映射。对于通用方法,请限制可以传递给它的类型。
谷歌有很多可以充实“如何”......但我希望它能指出你正确的方向。
答案 1 :(得分:1)
一些注意事项:
newRecord
不应键入dynamic
。你知道它是T
- 声明它是这样的。Convert
- 我愿意打赌你不理解它的语义(我确实试图避免了解所有奇怪的角落情况);即使你这样做,盲目转换类型通常也是隐藏错误的好方法。MetadataToken
排序并重新排序源顺序,但依靠这个来确定正确性是不可取的。更好的想法是按名称将列与属性匹配 - 您可以通过record.Table.Columns
获取所有列。微博客不会规定你使用sql的方式;它只将C#对象映射到从数据库中获取的行,反之亦然;这意味着它们比LINQ更灵活,更容易迁移,这也意味着PetaPoco和Dapper比LINQ快得多,并且通常比手动编码更快,除非你真的注意正确使用低级api。