从 IDataReader 映射时,我可以将 AutoMapper 配置为读取自定义列名称吗?

发布于 2024-09-05 21:25:00 字数 666 浏览 3 评论 0原文

用于映射配置的伪代码(如下)是不可能的,因为 lambda 只允许我们访问 IDataReader 类型,而在实际映射时,AutoMapper 将到达每个 IDataRecord 的每个“单元格”,而 IDataReader .Read() == true

var mappingConfig = Mapper.CreateMap<IDataReader, IEnumerable<MyDTO>>();
mappingConfig.ForMember(
    destination => destination.???,
    options => options.MapFrom(source => source.???));

任何人都可以想出一种在运行时使用 AutoMapper 配置或仅满足以下要求的其他动态方法来执行此操作的方法。

要求是支持任何传入的 IDataReader ,其列名称可能与 MyDTO 的属性名称不匹配,并且没有我可以依赖的命名约定。相反,我们会要求用户在运行时通过 IDataReader.GetSchemaTable() 交叉引用预期的列名称与在 IDataReader 中找到的实际列名称。

Psuedo code for mapping configuration (as below) is not possible since the lambda only lets us access Type IDataReader, wheras when actually mapping, AutoMapper will reach into each "cell" of each IDataRecord while IDataReader.Read() == true:

var mappingConfig = Mapper.CreateMap<IDataReader, IEnumerable<MyDTO>>();
mappingConfig.ForMember(
    destination => destination.???,
    options => options.MapFrom(source => source.???));

Can anyone think of a way to do this using AutoMapper configuration at runtime or just some other dynamic approach that meets the requirement below.

The requirement is to support any incoming IDataReader which may have column names that don't match the property names of MyDTO and there is no naming convention I can rely on. Instead we'll ask the user at runtime to cross-reference the expected column names with the actual column names found in the IDataReader via IDataReader.GetSchemaTable().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

喜你已久 2024-09-12 21:25:00

我不知道 automapper,但我使用 ValueInjecter 将 datareader 映射到对象,如下所示

 while (dr.Read())
 {
    var o = new User();
    o.InjectFrom<DataReaderInjection>(dr);
    return o;
 }

: DataReaderInjection(类似于 Automapper 的 ValueResolver),

public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
    {
        protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
        {
            for (var i = 0; i < source.FieldCount; i++)
            {
                var activeTarget = targetProps.GetByName(source.GetName(i), true);
                if (activeTarget == null) continue;

                var value = source.GetValue(i);
                if (value == DBNull.Value) continue;

                activeTarget.SetValue(target, value);
            }
        }
    }

您可以使用它将值从 IDataReader 注入到任何类型的对象


ok, so according to your requirements, I guess it should be like this:

public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
        {
            protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
            {
                var columns = source.GetSchemaTable().Columns;
                for (var i = 0; i < columns.Count; i++)
                {
                    var c = columns[i];

                    var targetPropName = c.ColumnName; //default is the same as columnName

                    if (c.ColumnName == "Foo") targetPropName = "TheTargetPropForFoo";
                    if (c.ColumnName == "Bar") targetPropName = "TheTargetPropForBar";
                    //you could also create a dictionary and use it here

                    var targetProp = targetProps.GetByName(targetPropName);
                    //go to next column if there is no such property in the target object
                    if (targetProp == null) continue;

                    targetProp.SetValue(target, columns[c.ColumnName]);
                }
            }
        }

在这里我使用了 GetSchemaTable,就像你想要的:)


ok, if you want to pass some stuff to the injection, you can do it in many ways, here's how:

o.InjectFrom(new DataReaderInjection(stuff), dr);
//you need a constructor with parameters for the DataReaderInjection in this case

var ri = new DataReaderInjection();
ri.Stuff = stuff;
o.InjectFrom(ri, dr);
//you need to add a property in this case

这是一个提示(对于带参数的构造函数)

  public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
     {
        private IDictionary<string, string> stuff;
        public DataReaderInjection(IDictionary<string,string> stuff)
        {
          this.stuff = stuff;
        }
                    protected override void Inject(
...

I don't know about automapper but I'm mapping datareader to objects using the ValueInjecter like this:

 while (dr.Read())
 {
    var o = new User();
    o.InjectFrom<DataReaderInjection>(dr);
    return o;
 }

and the DataReaderInjection (something like ValueResolver for Automapper)

public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
    {
        protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
        {
            for (var i = 0; i < source.FieldCount; i++)
            {
                var activeTarget = targetProps.GetByName(source.GetName(i), true);
                if (activeTarget == null) continue;

                var value = source.GetValue(i);
                if (value == DBNull.Value) continue;

                activeTarget.SetValue(target, value);
            }
        }
    }

you can use this to inject values from an IDataReader to any type of object


ok, so according to your requirements, I guess it should be like this:

public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
        {
            protected override void Inject(IDataReader source, object target, PropertyDescriptorCollection targetProps)
            {
                var columns = source.GetSchemaTable().Columns;
                for (var i = 0; i < columns.Count; i++)
                {
                    var c = columns[i];

                    var targetPropName = c.ColumnName; //default is the same as columnName

                    if (c.ColumnName == "Foo") targetPropName = "TheTargetPropForFoo";
                    if (c.ColumnName == "Bar") targetPropName = "TheTargetPropForBar";
                    //you could also create a dictionary and use it here

                    var targetProp = targetProps.GetByName(targetPropName);
                    //go to next column if there is no such property in the target object
                    if (targetProp == null) continue;

                    targetProp.SetValue(target, columns[c.ColumnName]);
                }
            }
        }

here I used GetSchemaTable, just like you wanted :)


ok, if you want to pass some stuff to the injection, you can do it in many ways, here's how:

o.InjectFrom(new DataReaderInjection(stuff), dr);
//you need a constructor with parameters for the DataReaderInjection in this case

var ri = new DataReaderInjection();
ri.Stuff = stuff;
o.InjectFrom(ri, dr);
//you need to add a property in this case

here's a hint (for the constructor with parameters way)

  public class DataReaderInjection : KnownSourceValueInjection<IDataReader>
     {
        private IDictionary<string, string> stuff;
        public DataReaderInjection(IDictionary<string,string> stuff)
        {
          this.stuff = stuff;
        }
                    protected override void Inject(
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文