Extension method to convert SubSonic SqlQuery object to plain SQL - c#

I sometimes need to see what SQL statement SubSonic generates.
That works great with:
SqlQuery qry = DB.Select().From<Product>()
.Where(Products.Columns.Name).IsEqualTo("Productname");
Console.WriteLine(qry.BuildSqlStatement());
However that returns the query with parameters (SELECT ... WHERE productname = ?productname). So, I always have to find the real values in my code and replace the parameters with the propper formatted value (e.g. productname = 'Productname') which can be really annoying with complex querys.
So, I decided to make an extension method that I want to share (look at my answer for the code).

It is far away from being perfect, but it fits my needs for now.
But I can use
Console.WriteLine(qry.BuildSqlStatementDebug());
then copy the result to Clipboard and run it agains my DB from Query Browser.
using System;
using SubSonic;
namespace MyNamespace.ExtensionMethods
{
public static class SubsonicSqlQueryExtensionMethods
{
public static String BuildSqlStatementDebug(this SqlQuery qry)
{
var result = qry.BuildSqlStatement();
foreach (var c in qry.Constraints)
{
if (c.Comparison == Comparison.BetweenAnd)
{
result = result.Replace(c.ParameterName + "_start", GetFormattedValue(c.StartValue, c.DbType));
result = result.Replace(c.ParameterName + "_end", GetFormattedValue(c.EndValue, c.DbType));
}
else
{
result = result.Replace(c.ParameterName, GetFormattedValue(c.ParameterValue, c.DbType));
}
}
return result;
}
// Works for MySQL
private static readonly String formatter_date = "'{0:yyyy-MM-dd}'";
private static readonly String formatter_datetime = "'{0:yyyy-MM-dd hh:mm:ss}'";
private static readonly String formatter_string = "'{0}'";
private static String GetFormattedValue(Object value, System.Data.DbType type)
{
switch (type)
{
case System.Data.DbType.AnsiString:
return String.Format(formatter_string, value);
case System.Data.DbType.AnsiStringFixedLength:
return String.Format(formatter_string, value);
//case System.Data.DbType.Binary:
// break;
case System.Data.DbType.Boolean:
return (Boolean)value == true ? "true" : "false";
//case System.Data.DbType.Byte:
// break;
//case System.Data.DbType.Currency:
// break;
case System.Data.DbType.Date:
return String.Format(formatter_date, value); break;
case System.Data.DbType.DateTime:
return String.Format(formatter_datetime, value); break;
case System.Data.DbType.DateTime2:
return String.Format(formatter_datetime, value); break;
//case System.Data.DbType.DateTimeOffset:
// break;
//case System.Data.DbType.Decimal:
// break;
//case System.Data.DbType.Double:
// break;
case System.Data.DbType.Guid:
return String.Format(formatter_string, value);
//case System.Data.DbType.Int16:
// break;
//case System.Data.DbType.Int32:
// break;
//case System.Data.DbType.Int64:
// break;
//case System.Data.DbType.Object:
// break;
//case System.Data.DbType.SByte:
// break;
//case System.Data.DbType.Single:
// break;
case System.Data.DbType.String:
return String.Format(formatter_string, value);
case System.Data.DbType.StringFixedLength:
return String.Format(formatter_string, value);
//case System.Data.DbType.Time:
// break;
//case System.Data.DbType.UInt16:
// break;
//case System.Data.DbType.UInt32:
// break;
//case System.Data.DbType.UInt64:
// break;
//case System.Data.DbType.VarNumeric:
// break;
case System.Data.DbType.Xml:
return String.Format(formatter_string, value);
default:
return value.ToString();
}
}
}
}

Related

How to get the month name using Dictionary in C#?

I have implemented the first three letters of the month to full name of the month in get Full Month function it is returned based on three letters .
But how to implemented in Dictionary concept Any one simplify modify this code given below code:
**public static string getFullMonth(string mthname)
{
string Mthname = "";
switch (mthname.ToUpper())
{
case "JAN":
Mthname ="January";
break;
case "FEB":
Mthname = "February";
break;
case "MAR":
Mthname = "March";
break;
case "APR:":
Mthname = "April";
break;
case "MAY":
Mthname = "May";
break;
case "JUN":
Mthname = "June";
break;
case "JUL":
Mthname = "July";
break;
case "AUG":
Mthname = "August";
break;
case "SEP":
Mthname = "September";
break;
case "OCT":
Mthname = "October";
break;
case "NOV":
Mthname = "November";
break;
case "DEC":
Mthname = "December";
break;
default:
Console.WriteLine("Invalid grade");
break;
}
return Mthname;
}**
simplify this code given below code
Yes, don't use a dictionary at all:
public static string GetFullMonth(string englishShortMonthName)
{
CultureInfo englishCulture = CultureInfo.InvariantCulture;
if (DateTime.TryParseExact(englishShortMonthName, "MMM", englishCulture, DateTimeStyles.None, out DateTime dt))
return dt.ToString("MMMM", englishCulture);
return englishShortMonthName;
}
Read about the month ("M", "m") format specifier
Look up Dictionary syntax. Ultimately you're looking for something like this:
var monthNames = new Dictionary<string, string>
{
{ "JAN", "January" },
{ "FEB", "February" },
...
}
Please find complete solution
public static string getFullMonth(string mthname)
{
var monthNames = new Dictionary<string, string>
{
{ "JAN", "January" },
{ "FEB", "February" },
...
}
return monthNames[mthname];
}
But above code looks weird So You should create dictionary globally and initialize in constructor.
Add only below line in getFullMonth function.
return monthNames[mthname];

How to store outcome of switch statement into an object in c#

Is it possible to create an object that stores the outcome of the switch statement in c#? Because my end goal is to compare the object in an if statement, and if that's true then it will print a writeline.
switch (results)
{
case 1:
checkingWriter.WriteLine("text");
break;
case 0:
checkingWriter.WriteLine("text");
error_Found = true;
break;
case -1:
checkingWriter.WriteLine("text");
error_Found = true;
break;
case -2:
checkingWriter.WriteLine("text");
error_Found = true;
break;
case -3:
checkingWriter.WriteLine("text");
error_Found = true;
break;
}
You are mixing both side effects and the computation of a value; this is a bad code smell and you might consider separating that logic.
To address your specific question: at this time there is no easy way to get a value computed by a particular switch case section out of the switch. However, this feature has been proposed for C# 8.0, so it seems likely that you'll get some version of this. See the link below for the proposal:
https://neelbhatt.com/2018/05/19/c-8-0-expected-features-part-iii-switch-statments/
Yes, something like (but very basic since we do not have any details):
var objectToCheck = ...; // Some initialized value or null
switch(...)
{
case ...:
objectToCheck = ...
break;
case ...:
objectToCheck = ...
break;
...
default:
Error handling
}
if (objectToCheck ==/.Equals(...) ) // Check object
create variable before switch statement begins, store the switch case result in variable. After switch ends, use the variable in the if condition.
var result = null;
switch (caseSwitch)
{
case 1:
result = fn1();
break;
case 2:
result = fn2();
break;
default:
Console.WriteLine("Default case");
break;
}
if(result == 'your condition')
do something
There are not enough details but may this works, or give you a new idea:
public class Foo
{
public static bool operator !=(Foo foo1, int results){
return results <= 0;
}
public static bool operator ==(Foo foo1, int results){
switch(results)
{
case 1:
Console.WriteLine("All gones good");
return false;
case 0:
Console.WriteLine("Nothing happend");
break;
case -1:
Console.WriteLine("Error 183");
break;
case -2:
Console.WriteLine("Fatal Error");
break;
case -3:
Console.WriteLine("The user doesn't exists");
break;
default:
return false;
}
return true;
}
}
And when you use it:
public static void Main()
{
Foo foo = new Foo();
int results = 0;
// makes some logic that fills results
if(foo == results){
Console.WriteLine("Do Something Custom Here");
}
results = -1;
if(foo == results){
Console.WriteLine("Do Another Something Custom Here");
}
}
It will give you in console something like this:
//Nothing happend
//Do Something Custom Here
//Error 183
//Do Another Something Custom Here

C# Switch-case string end with

Is there any way to make a case condition in a switch statement where you say if a string end with something?
switch (Pac.Sku)
{
case "A":
pacVM.Sucursal = "Managua";
break;
case "B":
pacVM.Sucursal = "Masaya";
break;
case "C":
pacVM.Sucursal = "Leon";
break;
default:
pacVM.Sucursal = "N/A";
break;
}
Get the last character of the string, and switch over the result:
switch (Pac.Sku.Last())
{
case 'A':
pacVM.Sucursal = "Managua";
break;
case 'B':
pacVM.Sucursal = "Masaya";
break;
case 'C':
pacVM.Sucursal = "Leon";
break;
default:
pacVM.Sucursal = "N/A";
break;
}
If the string could be null or empty use something like this function instead of Last(). This function returns null if the string is null, null if the string is empty, and the last character of the string if it is not null or empty:
char? GetLast(string s)
{
return s?.Length > 0 ? s.Last() : (char?)null;
}
Switch:
switch(GetLast(Pac.Sku))
You can
use pattern matching feature of C# 7.0 to achieve this. Here is a very basic example:
var t = "blah";
switch (t)
{
case var a when t.EndsWith("bl"):
Console.WriteLine("I'm not here");
break;
case var b when t.EndsWith("ah"):
Console.WriteLine("I'm here");
break;
}
You can get creative with a Func<string, string>[] like this:
Func<string, string>[] cases = new Func<string, string>[]
{
x => x.EndsWith("A") ? "Managua" : null,
x => x.EndsWith("B") ? "Masaya" : null,
x => x.EndsWith("C") ? "Leon" : null,
x => "N/A",
};
Func<string, string> #switch = cases.Aggregate((x, y) => z => x(z) ?? y(z));
string result = #switch(Pac.Sku);
I have tested this with sample input that matches each of the cases and it works just fine.
One significant advantage with this approach is that you can build the Func<string, string>[] at run-time. Nice for creating configurable solutions.
You're also not limited to just using EndsWith - any condition can be used that suits the purpose.
I think it's not a way!
You can only use the if-else
if (Pac.Sku.EndsWith("A") )
{
pacVM.Sucursal= "Managua";
}
else if (Pac.Sku.EndsWith("B"))
{
pacVM.Sucursal= "Masaya";
}
else if (Pac.Sku.EndsWith("C"))
{
pacVM.Sucursal= "Leon";
}
else
{
pacVM.Sucursal= "N/A";
}

Kendo Grid get property value with type in ClientTemplate

I've broken my mind with Kendo library.
I'm trying to do something like that:
c.Bound(m => m.Transaction).Title().ClientTemplate(Html.TransactionStateFormat(*currentValue*);
And my Html helper below:
public static string TransactionStateFormat(this HtmlHelper helper, TransactionState value)
{
string result;
switch (value)
{
case TransactionState.Applied:
result = "# <img src='/Content/img/checkbox-circle-small-2.png'/> #";
break;
case TransactionState.OptOut:
result = "# <img src='/Content/img/cross-sircle-small.png'/> #";
break;
case TransactionState.Undefined:
result = "# N/A #";
break;
default:
result = "# N/A #";
break;
}
return result;
}
The question is how to get current value of Transaction to put it in to the html helper method? Or how to make the same thing by another way? Any suggestions?
You can use the following
c.Bound(m => m.Transaction).Title().ClientTemplate("#=TransactionStateFormat(data)#");
public enum TransactionState: int
{
Applied = 0,
OptOut=1,
Undefined=2
}
and you add this javascript function
<script>
function TransactionStateFormat(data)
{
var result='';
switch (data.Transaction)
{
case 0:
result = "<img src='/Content/img/checkbox-circle-small-2.png'/>";
break;
case 1:
result = "<img src='/Content/img/cross-sircle-small.png'/>";
break;
case 2:
result = "N/A";
break;
default:
result = "N/A";
break;
}
return result;
}
</script>
hope it will help you

C# Parse SqlDbType Conversion

Is there any way to do something like this:
(SqlDbType.Int).Parse(dtbDataTable.Rows[0]["Id"])
Posting back my workaround:
public static string ParseValue(SqlDbType psdtParameter, string pstrValue, string pstrDateFormat = null)
{
object objReturn = new object();
if (pstrValue != "")
{
switch (psdtParameter.ToString())
{
case "BigInt":
objReturn = TypeDescriptor.GetConverter(typeof(Int64)).ConvertFromString(pstrValue);
break;
case "Bit":
objReturn = TypeDescriptor.GetConverter(typeof(Boolean)).ConvertFromString(pstrValue);
break;
case "NText":
case "NVarChar":
case "VarChar":
case "NChar":
case "Text":
case "Char":
objReturn = TypeDescriptor.GetConverter(typeof(String)).ConvertFromString(pstrValue);
break;
case "SmallDateTime":
case "DateTime":
objReturn = DateTime.ParseExact(pstrValue, pstrDateFormat, CultureInfo.InvariantCulture);
//TypeDescriptor.GetConverter(typeof(DateTime)).ConvertFromString(pstrValue);
break;
case "Money":
case "SmallMoney":
case "Decimal":
objReturn = TypeDescriptor.GetConverter(typeof(Decimal)).ConvertFromString(null, CultureInfo.InvariantCulture, pstrValue);
break;
case "Float":
objReturn = TypeDescriptor.GetConverter(typeof(Double)).ConvertFromString(pstrValue);
break;
case "Binary":
case "VarBinary":
case "Timestamp":
case "Image":
objReturn = TypeDescriptor.GetConverter(typeof(Byte[])).ConvertFromString(pstrValue);
break;
case "Int":
objReturn = TypeDescriptor.GetConverter(typeof(Int32)).ConvertFromString(pstrValue);
break;
case "Real":
objReturn = TypeDescriptor.GetConverter(typeof(Single)).ConvertFromString(pstrValue);
break;
case "SmallInt":
objReturn = TypeDescriptor.GetConverter(typeof(Int16)).ConvertFromString(pstrValue);
break;
case "TinyInt":
objReturn = TypeDescriptor.GetConverter(typeof(Byte)).ConvertFromString(pstrValue);
break;
}
return objReturn.ToString();
}
else
{
return null;
}
}
Tks!
Unfortunately no. SqlDbType is an enum, so (SqlDbType.Int) actually boils down to an integer value, not a type. The only way I can think of to do this is some sort of switch statement:
switch (SqlDbType dbType)
{
case SqlDbType.Int:
int value = Int32.Parse(dtbDataTable.Rows[0]["Id"]);
//Do stuff with this value
//repeat for other types
}
I think that would be tough to do, and it's not the most readable way. I handle this via extension methods to help with TinyInt, SmallInt, and nullable values across the board. E.g.:
using (var dr = new SafeDataReader(cmd.ExecuteReader()) {
while (dr.Read()) {
int? id = dr.GetNullableIntFromSqlTinyInt(0);
// Other stuff like that to handle type conversions
}
}
SafeDataReader is part of the CSLA business object framework, but you could implement your own DataReader if you would like. It's a lot more legible and encapsulates all the parsing logic behind the scenes to the extension method.

Categories