开发者

Using linq for validation/ throwing exception

This may be the wrong way to do things(!) but i am just wondering ....

I am using

        //check that all transform fields have corresponding database columns
        foreach (string sDatabaseFieldName in l_sDatabaseFieldNames)
        {
            bool bFound = false;
            foreach (SqlParameter sqlp in sqlcmdAll.Parameters)
            {
                if (sqlp.SourceColumn == sDatabaseFieldName) bFound = true;
            }
            if (!bFound)
         开发者_运维知识库   {
                throw new Exception(string.Format("Transform field {0} does not have a corresponding column in the target table.", sDatabaseFieldName));
            }
        }

where l_sDatabaseFieldNames is a List< string> and sqlcmdAll is an insert SqlCommand with validated parameter names.

I want to throw an exception if an item in l_sDatabaseFieldNames is not in any sqlcmdAll.Parameters.SourceColumn. In other words all column names contained in l_sDatabaseFieldNames should also have a matching parameter (compared using SourceColumn property).

I can also use

bool bFound = l_sDatabaseFieldNames.All(sDBFN => sqlcmdAll.Parameters.Cast<SqlParameter>().Any(param => sDBFN == param.SourceColumn));

but i only get a true/false result.

Can i use a combination of the two techniques and throw an exception from within the linq query if an item is in l_sDatabaseFieldNames, but not in any sqlcmdAll.Parameters.SourceColumn?

Thank you in advance, James.


What exception would you expect it to throw? I feel this is better for you to take the result and throw the exception you want to throw:

if (!l_sDatabaseFieldNames.All(sDBFN => sqlcmdAll.Parameters.Cast<SqlParameter>().Any(param => sDBFN == param.SourceColumn)))
{
    throw new YourCustomException("Your custom message");
}

Of course, if this is for debugging purposes only to verify a condition in testing and you don't need it to go into the actual release code you can use an assertion:

Debug.Assert(l_sDatabaseFieldNames.All(sDBFN => sqlcmdAll.Parameters.Cast<SqlParameter>().Any(param => sDBFN == param.SourceColumn)));

* UPDATE *

Based on your comment, you have a few choices, basically. We could bastardize a select clause but I don't like this as it feels kinda weird throwing in a projection. Sadly Linq doesn't already have a ForEach() that lets you perform an Action<T>, so you can either write your own ForEach() for IEnumerable<T>, or you can use ToList() to convert the sequence to a List<T> which does have a ForEach():

        sqlcmdAll.Parameters.Cast<SqlParameter>().ToList().ForEach(p =>
            {
                if (!l_sDatabaseFieldNames.Contains(p.SourceColumn))
                {
                    throw new Exception("Could not find " + p.SourceColumn);
                }
            });

If you don't mind writing your own extension method, you can add this to your library (comes in very handy) to give ForEach() to IEnumerable:

public static class EnumerableExtensions
{
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source,
            Action<T> action)
    {
        if (source == null) throw new ArgumentNullException("source");

        foreach (T element in source)
        {
            action(element);
        }

        return source;
    }
}

Which would let you do this instead of using ToList():

        sqlcmdAll.Parameters.Cast<SqlParameter>().ForEach(p =>
            {
                if (!l_sDatabaseFieldNames.Contains(p.SourceColumn))
                {
                    throw new Exception("Could not find " + p.SourceColumn);
                }
            });


You could select the first non matching parameter

SqlParameter sqlp = sqlcmdAll.Parameters.Cast<SqlParameter>().Where(param => !l_sDatabaseFieldNames.Contains(param.SourceColumn)).FirstOrDefault();

if (sqlp != null)
    throw new Exception(string.Format("Transform field {0} does not have a corresponding column in the target table.", sqlp.SourceColumn));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜