web-dev-qa-db-fra.com

Exception EF: les données de chaîne ou binaires seraient tronquées. La déclaration est terminée.?

J'ai lu de nombreux messages liés à ce problème, mais je n'ai pas trouvé de réponse. J'essaie de charger une grande quantité de données d'Excel dans SQL Server. Des milliers d'enregistrements. Et je reçois cette exception:

Chaîne ou des données binaires seront tronquées. La déclaration est terminée.

Évidemment, certaines valeurs dépassent la taille du champ dans la base de données. L'erreur provient de SQL Server AFIK.


Ma question - Comment pourrais-je savoir quel enregistrement et quelle valeur de champ ont causé cela?

Il n'y a pas de détails spécifiques dans l'exception EF, à l'exception de celui que j'ai mentionné.

Toute aide est appréciée.

Certains ont demandé le fragment de code, mais c'est en fait très simple, le problème n'est pas avec le code:

// employees is a List<Employee> collection loaded from Excel
using (var context = new Entities())
{
    employees.ForEach(e => context.Employee.AddObject(e));
    context.SaveChanges();
}

De plus, l'approche suggérée pour utiliser DbEntityValidationException (qui n'est disponible que dans Entity Framework 5.0) ne fonctionne pas, le bloc catch n'a pas intercepté l'exception.

try
{
    ImportData();
}
catch (DbEntityValidationException ex)
{
    foreach (var item in ex.EntityValidationErrors)
    {
        //...
    }
}

La seule solution que j'ai trouvée jusqu'à présent consiste à utiliser SQL Server Profiler et à définir les événements suivants à surveiller:

enter image description here

enter image description here

Maintenant, je peux voir que l'e-mail est trop long.

35
monstro
catch (DbEntityValidationException ex)
{
    foreach (var item in ex.EntityValidationErrors)
    {
        //... inspect here 
    }
}

Vous pouvez trouver les informations dont vous avez besoin dans chaque boucle.

J'espère que cela pourra aider.

5
Cuong Nguyen

Vous ne pouvez pas à ce niveau. SQL Server rejette la requête entière.

J'ajouterais des vérifications préalables aux données par rapport aux contraintes de votre base de données pour la taille des chaînes, les formats de date, etc.

Vous pouvez également TRIM chaque champ de chaîne dans les données brutes à la taille de champ correspondante avant d'essayer d'insérer.

5
D Stanley

Vous pouvez vérifier les données avant l'enregistrement, en utilisant les métadonnées EF, et déclencher l'erreur appropriée.

1
Ben
private static string 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"))
                {
                    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);

                    if (!string.IsNullOrEmpty(currentValue) && currentValue.Length > maxLength && lengthString!="max")
                        return testObject.GetType().Name + "." + propInfo.Name + " " + currentValue + " Max: " + maxLength;

                }
            }
        }
        return "";
    }


foreach (object insert in dtx.GetChangeSet().Inserts)
            {
                string result = FindLongStrings(insert);
                if (string.IsNullOrEmpty(result) == false)
                {
                    responseBuilder.Append(result);
                }
            }

Si responseBuilder n'est pas vide, il contient le nom du champ, la longueur autorisée et le message d'erreur.

0
Ali

Vous n'êtes pas sûr de la troncature en particulier, mais voici une astuce pour savoir quand vous obtenez une exception qui vous indique d'examiner EntityValidationErrors. Habituellement, lors du débogage, il ne vous permettra pas de voir cette propriété (sauf si vous avez déjà eu une capture explicite). Cependant, vous pouvez ouvrir la veille rapide et taper $exception. Vous devriez maintenant pouvoir explorer et trouver cette propriété. Vous pouvez également simplement taper ce qui suit:

(System.Data.Entity.Validation.DbEntityValidationException)$exception
0
ShawnFumo