简体   繁体   English

如何将多个属性组合到一个列表中<string> C# 中的属性</string>

[英]How to combine many properties into one List<string> property in C#

I am a little bit confused about how to read data from Excel.我对如何从 Excel 读取数据有点困惑。 I am trying to import Excel for updating product list, I create an Excel model;我正在尝试导入 Excel 以更新产品列表,我创建了 Excel model; I added all basic properties like name, price, quantity, etc. into this model.我将名称、价格、数量等所有基本属性添加到此 model 中。 I will read all Excel and map into this model.我会将所有 Excel 和 map 读入这个 model。 That's ok, then I will give this model to EF Core 5 to save to SQL Server.没关系,那我把这个 model 给 EF Core 5 保存到 SQL 服务器。

public class ExcelModel
{ 
    public string Name { get; set }
    public int Price { get; set }
    public int Quantity { get; set }
}

I have a problem with product options.我对产品选项有疑问。 According to my DB schema, I have one table of products, one for options, one for option values, one for productOptionRelation.根据我的数据库模式,我有一张产品表,一张用于选项,一张用于选项值,一张用于 productOptionRelation。

在此处输入图像描述

Can you suggest another solution way or just solve on my way?你能建议另一种解决方案还是按我的方式解决?

My colleges did this created field corresponding to values.我的大学创建了与值相对应的字段。 like option1 and optionValue1, option2 and optionValue2 many of them, because each product could have many options.像 option1 和 optionValue1, option2 和 optionValue2 其中很多,因为每个产品可以有很多选项。 Model look like that, 20 option and 20 value was declared here and they manually map all these Model 看起来像这样,这里声明了 20 个选项和 20 个值,他们手动 map 所有这些

坏模型的图片

For a temporary solution, I limited this option up to 5 and I created an list.对于临时解决方案,我将此选项限制为 5,并创建了一个列表。 and encapsulate all of them into list并将它们全部封装到列表中

public class ExcelOptionViewModel
{
    public string Option { get; set; }
    public string Value { get; set; }
}

This is my temp model, I encapsulated like that.这是我的临时 model,我是这样封装的。

 public IList<ExcelOptionViewModel> OptionModels { get; set; } = new List<ExcelOptionViewModel>(); 

 public string Option1
 {
     get { return OptionModels[0].Option; } 
     set
     {
         this.OptionModels.Insert(0, new ExcelOptionViewModel { Option = value });
     }
 }

 public string Option1Value
 {
     get { return OptionModels[0].Value; }
     set { this.OptionModels[0].Value  = value; }
 }

This would be unlimited, You should enter how much you want这将是无限的,您应该输入您想要的数量

I have 2 solutions still I am researching one is, creating a method inside the excelviewmodel, this method will add all options and values into a list or I will use reflection, I am looking something like underlying type I will all option and values this underlying base type or something, when property loop came here, checking the type and assign all option1,option2,option3 or name like that properties to List<string> options , and same for the option values.我有 2 个解决方案我仍在研究一个是,在 excelviewmodel 中创建一个方法,此方法会将所有选项和值添加到列表中,或者我将使用反射,我看起来像底层类型我将所有选项和值这个底层基本类型或其他东西,当属性循环来到这里时,检查类型并将所有 option1,option2,option3 或类似属性的名称分配给List<string> options ,对于选项值也是如此。 I will use reading like option[0] and optionvalue[0]我将使用像 option[0] 和 optionvalue[0] 这样的阅读

Excel column names must be different because I read excel and turn it into datatable. Excel 列名必须不同,因为我读取了 excel 并将其转换为数据表。 Datatable column names must be different, it's not valid for reading into datatable数据表列名必须不同,读入数据表无效

excel导入错误的样本

excel导入真实样本

I used basically excel to data table function I can't remember but probably I found it in StackOverflow.我基本上使用 excel 到数据表 function 我不记得了,但可能我在 StackOverflow 中找到了它。 Also, I added a feature there If some cell is null it will miss.另外,我在那里添加了一个功能如果某个单元格是 null 它会错过。

public List<T> ConvertDataTableToList<T>(DataTable dt)
{
    //datatable clomun names
    var columnNames = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName.ToLower()).ToList();

    //selection properties equals to columnnames because I dont want loop for all props
    var properties = typeof(T).GetProperties().Where(prp => columnNames.Any(t => t.ToLower() == prp.Name.ToLower()));

    return dt.AsEnumerable().Select(row =>
    {
        var objT = Activator.CreateInstance<T>();
        foreach (var pro in properties)
        {
            try
            {
                if (row[pro.Name] != DBNull.Value)
                    pro.SetValue(objT, row[pro.Name], null);
                else
                    pro.SetValue(objT, null, null);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        return objT;
    }).ToList();
}

I am looking something here when option1 or option2 comes here it would put this into a list当Option1或Option2来到这里时,我在这里寻找某些东西,它将其列入列表

Also in my dt to model converter I dont want to use If but if some data value is null It throws an error which cant convert from dbnull value.同样在我的 dt 到 model 转换器中,我不想使用 If 但如果某些数据值是 null 它会引发无法从 dbnull 值转换的错误。 If you have a suggest for it I would like release if condition:)如果您对此有建议,我想在条件下发布:)

When All done I will map this excelviewmodel to product model something like this完成后,我将 map 这个 excelviewmodel 到产品 model 类似这样的东西

 foreach (var prop in SideParams.columns)
            {
                var source = row.GetType().GetProperty(prop);

                var destination = product.GetType().GetProperty(prop);

                if (destination != null && source.GetValue(row) != null)
                {
                Type t = Nullable.GetUnderlyingType(destination.PropertyType) ?? destination.PropertyType;

                object safeValue = Convert.ChangeType(source.GetValue(row), t);
                destination.SetValue(product, safeValue);

            }
        }

I saw something here https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=net-6.0我在这里看到了一些东西https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=net-6.0

it about binding flangs when reflecting model.关于反射 model 时的绑定法兰。 "Specifies flags that control binding and the way in which the search for members and types is conducted by reflection." “指定控制绑定的标志以及通过反射进行搜索成员和类型的方式。” If there is way I can redirect option(1-2-3-4-5-6...) to list options如果有办法我可以将选项(1-2-3-4-5-6...)重定向到列表选项

thanks for the help I solved my problem.感谢您帮助我解决了我的问题。 If you need something like that, my solution is;如果您需要类似的东西,我的解决方案是;

As you know OptionModels is what I created before, AddOptipns function is a new one I use for add data to list, The function work with the ref, otherwise it must be static, if I turn it static, option models also must be static, so I can't access the list. As you know OptionModels is what I created before, AddOptipns function is a new one I use for add data to list, The function work with the ref, otherwise it must be static, if I turn it static, option models also must be static,所以我无法访问该列表。

 public IList<ExcelOptionViewModel> OptionModels { get; set; } = new List<ExcelOptionViewModel>();
 public void AddOptions(ref String option, ref String value)
     {
        OptionModels.Add(new ExcelOptionViewModel { Option = option.Trim(), Value = value.Trim() });
     }

And also add some new parts to convert model function,并且还添加了一些新零件来转换 model function,

calling that AddOptions method with reflection, I got an example from here https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=net-6.0用反射调用 AddOptions 方法,我从这里得到了一个例子https://docs.microsoft.com/en-us/dotnet/api/system.reflection.bindingflags?view=net-6.0

I was inspired by the swap example there.我受到了那里的交换示例的启发。

public List<T> ConvertDataTableToList<T>(DataTable dt)
    {
        var columnNames = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName.ToLower()).ToList();

        //selection properties equals to columnnames because I dont want loop for all props
        var type = typeof(T);
        var properties = type.GetProperties().Where(prp => columnNames.Any(t => t.ToLower() == prp.Name.ToLower())).ToList();

        var productOptions = columnNames.Where(x => x.Contains("option")).ToList() ?? new List<string>();

        return dt.AsEnumerable().Select(row =>
        {
            var objT = Activator.CreateInstance<T>();
            foreach (var pro in properties)
            {
                try
                {
                    if (row[pro.Name] != DBNull.Value)
                        pro.SetValue(objT, row[pro.Name], null);
                    else
                        pro.SetValue(objT, null, null);
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }

            for (var i = 0; i < productOptions.Count(); i += 2)
            {
                object[] argValues = new object[] { row[productOptions[i]].ToString(), row[productOptions[i + 1]].ToString() };
                String[] argNames = new String[] { "option", "value" } ;
                 
               var method =  type.GetMethod("AddOptions");
                method.Invoke(objT, argValues);
            }

            return objT;
        }).ToList();
    }

here is the added data:)这是添加的数据:)

添加数据的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM