Using Linq to Sql in C#, is there any way I can automatically truncate too-long data?

前端 未结 3 1899
孤城傲影
孤城傲影 2021-01-14 20:00

So, I\'m importing data from one database into another. There are about 5,000 records (so nothing ridiculous, but not small enough to eyeball). Is there an easy way to autom

相关标签:
3条回答
  • 2021-01-14 20:42

    Linq2Sql will generate a property like this:

        [Column(Storage="_Name", DbType="NVarChar(50) NOT NULL")]
        public string Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                if ((this._Name != value))
                {
                    this.OnNameChanging(value);
                    this.SendPropertyChanging();
                    this._Name = value;
                    this.SendPropertyChanged("Name");
                    this.OnNameChanged();
                }
            }
        }
    

    See how it calls a function called OnNameChanged? Just create a function with that name to do the truncation and logging:

    void OnNameChanged()
    {
        if (Name.Length > 50)
        {
            Name = Name.Substring(0, 50);
            LogSomehow("Name truncated");
        }
    }
    
    0 讨论(0)
  • 2021-01-14 20:49

    Here's a more automatic method. It looks at the type/length of each column being inserted, on the fly.

    Use it like this:

                foreach (object insert in context.GetChangeSet().Inserts)
                {
                    FindLongStrings(update);
                }
    
                context.SubmitChanges();
    

    And here's the method: (It's horribly inefficient so I wouldn't leave it in production code, but if you've got a one-time conversion/import (and it sound like you do), it might do the trick.)

        public static void FindLongStrings(object testObject)
        {
            foreach (PropertyInfo propInfo in testObject.GetType().GetProperties())
            {
                foreach (ColumnAttribute attribute in propInfo.GetCustomAttributes(typeof(ColumnAttribute), true))
                {
                    if (attribute.DbType.ToLower().Contains("varchar"))
                    {
                        // kinda crude, but it works...
                        string dbType = attribute.DbType.ToLower();
                        int numberStartIndex = dbType.IndexOf("varchar(") + 8;
                        int numberEndIndex = dbType.IndexOf(")", numberStartIndex);
                        string lengthString = dbType.Substring(numberStartIndex, (numberEndIndex - numberStartIndex));
                        int maxLength = 0;
                        int.TryParse(lengthString, out maxLength);
    
                        string currentValue = (string)propInfo.GetValue(testObject, null);
    
                        // Do your logging and truncation here
                        if (!string.IsNullOrEmpty(currentValue) && currentValue.Length > maxLength)
                            Console.WriteLine(testObject.GetType().Name + "." + propInfo.Name + " " + currentValue + " Max: " + maxLength);
    
                    }
                }
            }
        }
    
    0 讨论(0)
  • 2021-01-14 20:50

    I would make an extension iterator method that you could throw inline with your query, doing something like this:

    public static IEnumerable<string> Truncater(this IEnumerable<string> s, int len)
    {
        foreach( var str in s )
        {
            if( str.Length > len )
            {
                string outStr = str.Substring(0, len);
                Console.WriteLine(String.Format("Truncated {0} to {1}", str, outStr));
                yield return outStr;
            }
            else
                yield return str;
        }
    }
    
    0 讨论(0)
提交回复
热议问题