0

我写了一个小算法来比较 Linq DataContext 表和 sql 表。它遍历 Linq 表的属性并获取属性的 CustomeAttributes(表列)。它已经工作了多年,但有人创建了一个带有# 符号的表字段(UPS#)。由于显而易见的原因,Linq 不喜欢这样的名称。因此,它有一个名为“Name”的 ColumnAttribute 成员来处理交换。但是,我一直使用“存储”成员作为我的列名。您会认为如果“名称”成员存在,您会直接拿起它,但我找不到它来挽救我的生命。

这是代码。很感谢任何形式的帮助。

public static ColumnInfo[] GetColumnsInfo(Type linqTableClass)
    {
        // Just looking in the loop to see if I missed something.
        foreach (var fld in linqTableClass.GetProperties())
        {
            foreach (var attr in fld.CustomAttributes)
            {
                foreach (var arg in attr.NamedArguments)
                {
                    if (arg.MemberName == "Name")
                        Debug.WriteLine(arg.MemberName);

                    Debug.WriteLine("{0}", arg.MemberName);
                }
            }
        }

        var columnInfoQuery =
            from field in linqTableClass.GetProperties()
            from attribute in field.CustomAttributes
            from namedArgument in attribute.NamedArguments
            where namedArgument.MemberName == "DbType"
            select new ColumnInfo
            {
                //ColumnName = field.Name,
                ColumnName = namedArgument.MemberName,
                DatabaseType = namedArgument.TypedValue.Value.ToString(),
            };
        return columnInfoQuery.ToArray();
    }

这是表类中的属性:

[global::System.Data.Linq.Mapping.ColumnAttribute(Name="PEER_UPS#", Storage="_PEER_UPS_", DbType="Char(31) NOT NULL", CanBeNull=false)]
    public string PEER_UPS_
    {
        get
        {
            return this._PEER_UPS_;
        }
        set
        {
            if ((this._PEER_UPS_ != value))
            {
                this.OnPEER_UPS_Changing(value);
                this.SendPropertyChanging();
                this._PEER_UPS_ = value;
                this.SendPropertyChanged("PEER_UPS_");
                this.OnPEER_UPS_Changed();
            }
        }
    }
4

3 回答 3

0

这是我的建议:

[对不起,我的第一个例子确实太简单了]这是我的做法:

namespace LinqAttributes
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;

    public class ColumnInfo
    {
        public string ColumnName { get; set; }
        public string DatabaseType { get; set; }
    }

    public class Test
    {
        [System.Data.Linq.Mapping.ColumnAttribute(Name = "Whatever", Storage = "Whatever", DbType = "Char(20)", CanBeNull = true)]
        public string MyProperty { get; set; }

        [System.Data.Linq.Mapping.ColumnAttribute(Name = "PEER_UPS#", Storage = "_PEER_UPS_", DbType = "Char(31) NOT NULL", CanBeNull = false)]
        public string PEER_UPS_ { get; set; }
    }

    internal class Program
    {
        public static IEnumerable<ColumnInfo> GetColumnsInfo(Type type)
        {
            foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(type))
            {
            var columnAttribute = descriptor.Attributes
                .OfType<System.Data.Linq.Mapping.ColumnAttribute>().SingleOrDefault();
            if (columnAttribute != null)
            {
                yield return new ColumnInfo
                {
                    ColumnName = columnAttribute.Name,
                    DatabaseType = columnAttribute.DbType
                };
             }
            }
        }

        private static void Main(string[] args)
        {
            foreach (var item in GetColumnsInfo(typeof(Test)))
            {
                Debug.WriteLine(item.ColumnName);
            }            
        }
    }
}

刚刚测试过了。干杯!

于 2018-02-02T13:57:39.897 回答
0

我找不到完成这项工作的好方法。出于某种原因, ColumnAttribute 只是不想玩得很好。尽管这很丑,但它确实有效。

public class ColumnInfo
{
    public string ColumnName { get; set; }
    public string DatabaseType { get; set; }
}

public static IEnumerable<ColumnInfo> GetColumnsInfo(Type linqTableClass)
    {
        Debug.WriteLine(string.Format("Table: {0}", linqTableClass.Name));

        /// In-Case this has to grow in the future.  Using a list for the arg names to search for.  
        /// The primary arg should be in position 0 of the array.
        string dbTypeArgName = "DbType";
        string fldPrimayName = "Storage";
        string fldSecondaryName = "Name";
        List<string> fldArgnames = new List<string>() { fldPrimayName, fldSecondaryName };

        foreach (var fld in linqTableClass.GetProperties())
        {
            Debug.WriteLine(string.Format("Field Name: {0}", fld.Name));

            foreach (var attr in fld.GetCustomAttributesData().Cast<CustomAttributeData>()
                .Where(r => r.AttributeType == typeof(ColumnAttribute))
                .Where(a => a.NamedArguments
                    .Select(n => n.MemberName)
                    .Intersect(fldArgnames)
                    .Any()))
            {
                var fldName = attr.NamedArguments.Where(r => r.MemberName == fldSecondaryName).Count() != 0
                        ? attr.NamedArguments.Where(r => r.MemberName == fldSecondaryName).SingleOrDefault().TypedValue.Value.ToString()
                        : fld.Name;
                var fldType = attr.NamedArguments
                        .Where(r => r.MemberName == dbTypeArgName)
                        .Select(r => r.TypedValue.Value.ToString())
                        .SingleOrDefault();

                Debug.WriteLine(string.Format("\tTable Field Name {0} Table Type {1}", fldName, fldType));

                yield return new ColumnInfo()
                {
                    ColumnName = fldName,
                    DatabaseType = fldType,
                };
            }
        }
    }
于 2018-02-12T19:36:48.900 回答
0
public class City
{
    public City() { }

    [Column("id_city")]
    public int Id { get; private set; }
}

var obj = new City();
var pro = obj.GetType().GetProperties();

string columnAttribute = pro.GetCustomAttributes<ColumnAttribute>().FirstOrDefault().Name;

if(columnAttribute == "id_city") {
    //sucess
}
于 2021-06-09T21:06:50.340 回答