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));
精彩评论