The regex below is not what I exactly need:
Regex.Replace(value.ToString(), "[^0-9a-zA-Z]+", "")
I need to remove escape characters from my string because I am creating one SQL with string and when I have this character ' or this \r\n etc. my Sql generates an error, I cannot use : SqlParameter in this case as I just have a list of SQLs in string, but I can remove the characters that I don't want.
So, I only need to remove these characters:
\r \n ' /\
Added my codes as requested:
private static string ConvertWhetherUsesComas(object value)
{
// formats with comas or not
if (value is String)
{
// fix problem with break characters such as \/`'
value = String.Format("'{0}'", Regex.Replace(value.ToString(), "[^0-9a-zA-Z]+", ""));
}
else if (value is DateTime)
{
value = String.Format("'{0}'", value.SafeToDateTime(null).Value.ToString("yyyy-MM-dd hh:mm:ss tt"));
}
else if (value == null)
{
value = "NULL";
}
else if (value is Boolean)
{
value = value.SafeToBool(false) == false ? 0 : 1;
}
return value.ToString();
}
private static List<String> ConvertDiferencesToSql<T>(Differences<T> differences, string tableName, string primaryKey) where T : IHasId<int>
{
var result = new List<String>();
differences.New.ToList().ForEach(newItem =>
{
var fieldNames = new StringBuilder();
var fieldValues = new StringBuilder();
var properties = newItem.GetType().GetProperties().ToList();
properties.ForEach(f =>
{
var propertyName = f.Name.ToUpper() == "ID" ? primaryKey : f.Name;
var propertyValue = ConvertWhetherUsesComas(f.GetValue(newItem));
if (propertyValue == "NULL") return; // ignores null values
fieldNames.AppendFormat("{0},", propertyName);
fieldValues.AppendFormat("{0},", propertyValue);
});
var sqlFields = fieldNames.ToString(0, fieldNames.Length - 1);
var sqlValues = fieldValues.ToString(0, fieldValues.Length - 1);
result.Add(String.Format("INSERT INTO {0} ({1}) VALUES ({2});", tableName, sqlFields, sqlValues));
});
differences.Changed.ForEach(changedRecord =>
{
var fields = new StringBuilder();
changedRecord.ChangedFields.ForEach(changedField =>
{
var propertyName = changedField.Property == "ID" ? primaryKey : changedField.Property;
var propertyValue = ConvertWhetherUsesComas(changedField.NewValue);
fields.AppendFormat("{0}={1},", propertyName, propertyValue);
});
var sqlFields = fields.ToString(0, fields.Length - 1);
result.Add(String.Format("UPDATE {0} SET {1} WHERE {2}={3};", tableName, sqlFields, primaryKey, changedRecord.Id));
});
differences.Deleted.ForEach(deletedItem => result.Add(String.Format("DELETE FROM {0} WHERE {1}={2};", tableName, primaryKey, deletedItem.GetId())));
return result;
}
You can place these characters into a character class, and replace with string.Empty:
var rgx4 = new Regex(#"[\r\n'/\\]");
var tst = "\r \n ' /\\";
tst = rgx4.Replace(tst, string.Empty);
Result:
A character class usually executes faster, as with alternative list, there is a lot of back-tracking impeding performance.
If I understood correctly, you want something like this :
Regex.Replace(value.ToString(), "(\\\\n|\\\\r|'|\\/\\\\)+", "")
See here.
Related
I want to read settings from a text file.
string MySettingsFile = "Settings.txt";
Normally, the file would have 4 lines.
SettingA:Alpha1
SettingB:Bravo2
SettingC:Charlie1
SettingD:Delta6
I want to get each line in it's own variable, like this :
string MyAlpa = "Alpha1";
string MyBravo = "Bravo2";
string MyCharlie = "Charlie1";
string MyDelta = "Delta6";
Normally, I would just read the lines in a loop, reading each line and setting the string as I go.
If, however, Line 4 is missing, and I am looking for the part of the line after the colon, I get an error if I check for it like this...
MyDelta = MyDeltaSubstring(MyDelta.LastIndexOf(':') + 1);
Is there a way to 'check for the existence of a specific line' before I attempt to get the SubString (so it doesn't get an error), like in
a function separate that has try, catch, finally with return either the string I want or the word "Missing", if that line is missing (and then stop since there are no more lines)?
function DoesLineExist(int X, string myFile)
{
string MyString;
try ()
{
// read line X from file myFile
// get everything AFTER the ":" and put it in MyString
// ??? //
}
catch (ArgumentException null)
{
MyString = "Missing";
}
catch (ArgumentException e)
{
MyString = "Missing";
}
finally
{
MyString = ? // whatever we got From Line X (after ":")
}
return MyString; // only if line is missing
}
Is there a better way of doing this?
ReadAllLines or something maybe?
You need to first verify that that line is exist or not and then again check that is line contains key/value pair of settings is exist and then project your key value pair into dictionary and then get each setting to your variable by its key name.
Here i create a console app for your demonstration purpose.
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> dictSettings = new Dictionary<string, string>();
string MyAlpa = "";
string MyBravo = "";
string MyCharlie = "";
string MyDelta = "";
var lines = File.ReadAllLines(#"C:\Users\xxx\source\repos\ConsoleApp4\ConsoleApp4\Files\Sample.txt");
for (var i = 0; i < lines.Length; i += 1)
{
var line = lines[i];
//DoesLineExist(line);
if (!string.IsNullOrEmpty(line) && line.Contains(":"))
{
string settingKey = line.Split(':')[0];
string settingValue = line.Split(':')[1];
dictSettings.Add(settingKey, settingValue);
}
}
MyAlpa = dictSettings.ContainsKey("SettingA") ? dictSettings["SettingA"] : "";
MyBravo = dictSettings.ContainsKey("SettingB") ? dictSettings["SettingB"] : "";
MyCharlie = dictSettings.ContainsKey("SettingC") ? dictSettings["SettingC"] : "";
MyDelta = dictSettings.ContainsKey("SettingD") ? dictSettings["SettingD"] : "";
Console.WriteLine(MyAlpa);
Console.WriteLine(MyBravo);
Console.WriteLine(MyCharlie);
Console.WriteLine(MyDelta);
Console.ReadLine();
}
//private static void DoesLineExist(string line)
//{
// if (!string.IsNullOrEmpty(line) && line.Contains(":"))
// {
// string settingKey = line.Split(':')[0];
// string settingValue = line.Split(':')[1];
// dictSettings.Add(settingKey, settingValue);
// }
//}
}
Input:
SettingA:Alpha1
SettingB:Bravo2
SettingC:Charlie1
Output:
Input:
SettingA:Alpha1
SettingC:Charlie1
SettingD:
Output:
Here is few different way to build the dictionary or list object we will use later. The choice is simple are those key unique or do you have multiple value for some SettingB. If the relation is one-one a Dictionary could be a solution. Giving you access to method like ContainsKey
var regexDictionary = Regex.Matches( File.ReadAllText(path)
, "(?<key>.+):(?<value>.+)")
.OfType<Match>()
.Where(m => m.Success)
.ToDictionary(m => m.Groups["key"].Value.Trim(),
m => m.Groups["value"].Value.Trim());
var ObjList = File.ReadAllLines(path)
.Select(line => line.Split(':'))
.Select(x => new MyObject {
prop1 = x[0],
prop2 = x[1]
// etc
})
var linQDictionary = File.ReadAllLines(path)
.Select(line => line.Split(':'))
.ToDictionary(
c => x[0],
c => x[1]
);
Does the key exist in the dictionary?
if (!dictionary .ContainsKey("SettingB"))
{
Console.WriteLine("For key = \"SettingB\", value = {0}.", dictionary["SettingB"]);
}
In a list of object:
if (ObjList .Any(x=> x.prop1 == "SettingZ" ))
{
// Select the object.
}
I'm trying to query a DynamoDB that i have created using code from the Amazon docs with a few simple modifications. I'm trying to take the data i get and write it to a log file as strings. But all i can seem to get is this:
2013-02-22 20:21:37.9268|Trace|[System.Collections.Generic.Dictionary2+KeyCollection[System.String,Amazon.DynamoDB.Model.AttributeValue] System.Collections.Generic.Dictionary2+ValueCollection[System.String,Amazon.DynamoDB.Model.AttributeValue]]|
I've tried a few different things but all return either the same thing, or something very similar.
The code i'm using:
private static void GetCallsForRange()
{
AmazonDynamoDBConfig config = new AmazonDynamoDBConfig();
config.ServiceURL = "http://dynamodb.us-west-2.amazonaws.com";
AmazonDynamoDBClient client = new AmazonDynamoDBClient(config);
DateTime startDate = DateTime.Today.AddDays(-21);
string start = startDate.ToString("G", DateTimeFormatInfo.InvariantInfo);
DateTime endDate = DateTime.Today;
string end = endDate.ToString("G", DateTimeFormatInfo.InvariantInfo);
QueryRequest request = new QueryRequest
{
TableName = "Inquiry",
HashKeyValue = new AttributeValue { S = "+15555555555" },
RangeKeyCondition = new Condition
{
ComparisonOperator = "BETWEEN",
AttributeValueList = new List<AttributeValue>()
{
new AttributeValue { S = start },
new AttributeValue { S = end }
}
}
};
QueryResponse response = client.Query(request);
QueryResult result = response.QueryResult;
foreach (Dictionary<string, AttributeValue> item in response.QueryResult.Items)
{
string logMsg = String.Format("[{0} {1}]", item.Keys, item.Values);
Logging.LogTrace(logMsg);
}
}
You will need to iterate over each item in the response.QueryResult.Items. You could rewrite your loop like this (taken from the Amazon DynamoDB documentation):
foreach (Dictionary<string, AttributeValue> item in response.QueryResult.Items)
{
LogItem(item);
}
private void LogItem(Dictionary<string, AttributeValue> attributeList)
{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;
string logValue =
(value.S == null ? "" : value.S) +
(value.N == null ? "" : value.N.ToString()) +
(value.B == null ? "" : value.B.ToString()) +
(value.SS == null ? "" : string.Join(",", value.SS.ToArray())) +
(value.NS == null ? "" : string.Join(",", value.NS.ToArray())) +
(value.BS == null ? "" : string.Join(",", value.BS.ToArray()));
string logMsg = string.Format("[{0} {1}]", attributeName, logValue);
Logging.LogTrace(logMsg);
}
}
Essentially, you need to discover the "type" of the AttributeValue(String, Number, Binary, StringSet, NumberSet, BinarySet) and then output that to your log.
I hope that helps!
I have a dynamic String value which may contain values like this
"Apple ,Banana, , , , Mango ,Strawberry , "
I would like to filter this string like
"Apple,Banana,Mango,Strawberry".
I have tried with the following code and it works.
Is there any better approach to achieve the same in C#(.NET 2.0)?
/// <summary>
/// Convert "Comma Separated String" to "Comma Separated String"
/// </summary>
/// <param name="strWithComma">String having values separated by comma</param>
/// <returns>String separated with comma</returns>
private String CommaSeparatedString(String strWithComma)
{
String rtn = String.Empty;
List<String> newList= new List<string>();
if (String.IsNullOrEmpty(strWithComma))
{
return rtn;
}
String[] strArray = strWithComma.Split(",".ToCharArray());
if (strArray == null || strArray.Length == 0)
{
return rtn;
}
String tmpStr = String.Empty;
String separator=String.Empty;
foreach (String s in strArray)
{
if (!String.IsNullOrEmpty(s))
{
tmpStr =s.Replace(Environment.NewLine, String.Empty);
tmpStr = tmpStr.Trim();
if (!String.IsNullOrEmpty(tmpStr))
{
newList.Add(tmpStr);
}
}
}
if (newList != null && newList.Count > 0)
{
rtn = String.Join(",", newList.ToArray());
}
return rtn;
}
you can also use Regex:
string str = #"Apple ,,Banana, , , , Mango ,Strawberry , ";
string result = Regex.Replace(str, #"(\s*,\s*)+", ",").TrimEnd(',');
I believe the following should do the trick on any .NET version:
string[] TrimAll( string[] input )
{
var result = new List<string>();
foreach( var s in input )
result.Add( s.Trim() );
}
return result.ToArray();
}
var delimiters = new [] { ",", "\t", Environment.NewLine };
string result = string.Join(",", TrimAll( input.Split( delimiters, StringSplitOptions.RemoveEmptyEntries ) ) );
Edit: updated to deal with white-space, tabs and newline.
Assuming that your items do not contain spaces:
private String CommaSeparatedString(String strWithComma)
{
string[] tokens = strWithComma
.Replace(" ", "")
.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
return string.Join(",", tokens);
}
Now I'm not sure if C# 2.0 accepts the new char[] {','} syntax. If not, you can define the array somewhere else (as a class private member, for example).
Here's a one-liner:
var outputString = string.Join(",", inputString.Replace(" ", string.Empty).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
Regex regex = new Regex(#"\w(?:(?!,| ).)*");
var items = regex.Matches("Apple ,Banana, , , , Mango ,Strawberry , ").Cast<Match>().Select(m => m.Value);
.NET 2.0 Version
List<string> newList = new List<string>();
Regex regex = new Regex(#"\w(?:(?!,| ).)*");
string str = "Apple ,Banana, , , , Mango ,Strawberry , ";
MatchCollection matches = regex.Matches(str);
foreach (Match match in matches)
{
newList.Add(match.Value);
}
var result = Regex.Replace(strWithComma, ",+", ",").TimEnd(',');
result = Regex.Replace(result, "\s+", string.Empty);
With no regular expressions, no splits and joins, trims, etc, O(n) time. StringBuilder is a very good class to work with strings.
EDIT
If the string it doesn't end with a letter it will add a comma. So an extra TrimEnd(',') is added
string strWithComma = ",Apple ,Banana, , , , Mango ,Strawberry , \n John,";
var sb = new StringBuilder();
var addComma = false;
foreach (var c in strWithComma )
{
if (Char.IsLetter(c)) // you might want to allow the dash also: example Anne-Marie
{
addComma = true;
sb.Append(c);
}
else
{
if (addComma)
{
addComma = false;
sb.Append(',');
}
}
}
string rtn = sb.ToString().TrimEnd(',');
Warning this method will only apply for C# 3.0 or higher. Sorry guys didnt read the question well enough
This will work but it can be done much easier like:
string input = "apple,banana,, \n,test\n, ,juice";
var parts = from part in input.Split(',')
let trimmedPart = part.Replace("\n", "")
where !string.IsNullOrWhiteSpace(trimmedPart)
select trimmedPart;
string result = string.Join(",", parts);
I need to extract data from a text file in ASP .NET.
Example Data:
; comment
data = astringvalue
; comment
; string values
person = bob
animal = rabbit
; boolean values (yes / no)
isValid = yes
isAnimal = no
I will be creating a GUI control for each line that is not a comment.
What is the best way to extract each line and determine if it is a string or a Boolean value.
Performance is a must as the file can be quite large.
Edit: At some point i will have need to update the values with the updated ones from the web page.
private void ShowConfig()
{
string configLine = String.Empty;
using (TextReader tr = File.OpenText(#"textfile"))
{
do
{
configLine = tr.ReadLine();
if (!String.IsNullOrEmpty(configLine) && !configLine.Contains(Convert.ToChar(";")))
{
CreateControl(configLine);
}
} while (configLine != null);
}
private void CreateControl(string configline)
{
string lineHeader = string.Empty;
string lineValue = String.Empty;
for (int i = 0; i < configline.Length; i++)
{
if (configline[i] == Convert.ToChar("="))
{
lineHeader = configline.Remove(i).TrimEnd();
lineValue = configline.Remove(0, ++i).TrimStart();
if (GetValueType(lineValue) is CheckBox)
{
this.Panel1.Controls.Add(CreateCheckBox(lineValue, lineHeader));
}
else
{
this.Panel1.Controls.Add(CreateLabel(lineHeader));
this.Panel1.Controls.Add(CreateTextBox(lineValue, lineHeader));
}
this.Panel1.Controls.Add(CreateNewLine());
break;
}
}
}
private Control GetValueType(string Value)
{
switch (Value)
{
case "yes":
case "no":
return new CheckBox();
default:
return new TextBox();
}
}
In the future i will need to check for more value types than string and boolean.
How about something like this? However, I think that working any kind of serious type-recognition into this schema is likely to be error prone. Why not use a better serialization in the first place? Something that captures type info in the serialized data?
var data=#" ; comment
data = value
; comment
; string values
person = Bob
animal = Rabbit
; boolean values (yes / no)
isValid = yes
isAnimal = no";
var parsed = data
.Split(new[]{"\r\n","\r","\n"}, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Trim())
.Where(line => !line.StartsWith(";"))
.Select(line => line.Split('=').Select(item => item.Trim()))
.Where(kv => kv.Count() == 2)
.Select(kv => new{key = kv.First(), value = kv.Last()})
.Select(kv =>
new{kv.key, kv.value, isBool = Regex.IsMatch(kv.value,"yes|no")});
Taking #Rubens' comments on-board, if the data source is too large to load in at once, you could stream the data with the addition of a helper method:
static IEnumerable<string> Lines(string filename)
{
using (var sr = new StreamReader(filename))
{
while (!sr.EndOfStream)
{
yield return sr.ReadLine();
}
}
}
then:
Lines(#"c:\path\to\data")
.Select(line => line.Trim())
.Where(line => !line.StartsWith(";"))
.Select(line => line.Split('=').Select(item => item.Trim()))
.Where(kv => kv.Count() == 2)
.Select(kv => new{key = kv.First(), value = kv.Last()})
.Select(kv =>
new{kv.key, kv.value, isBool = Regex.IsMatch(kv.value,"yes|no")});
StreamReader sr = null;
while(!sr.EndOfStream)
{
string line = sr.ReadLine();
if (string.IsNullOrEmpty(line) || line.StartsWith(";")) continue;
string[] tokens = line.Split("= ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
if(tokens.Length == 2)
{
if("Yes".Equals(tokens[1], StringComparison.CurrentCultureIgnoreCase) ||
"No" .Equals(tokens[1], StringComparison.CurrentCultureIgnoreCase))
{
// boolean
}
else
{
// non boolean
}
}
}
I'm having a problem when passing nulls to a ExecuteCommand() method using linq. My code is similar to the one that follows:
public void InsertCostumer(string name, int age, string address)
{
List<object> myList = new List<object>();
myList.Add(name);
myList.Add(age);
myList.Add(address);
StringBuilder queryInsert = new StringBuilder();
queryInsert.Append("insert into Customers(name, address) values ({0}, {1}, {2})");
this.myDataContext.ExecuteCommand(queryInsert.ToString(), myList.ToArray());
}
But, when a parameter is null (address, for instance), I get the following error: "A query parameter cannot be of type 'System.Object'."
The error doesn't occur if no parameters are null. I know the design in my example is a little poor, I just created a simplified example to focus on the problem. Any suggestions?
This is a known bug and Microsoft does not intend to fix it...
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=305114&wa=wsignin1.0
The work around is to either:
Drop into ADO.NET and execute the SQL Command directly
Format the string you're executing yourself and call ExecuteCommand with an empty object array (new object[0])
The second isn't a good idea as it opens you up to SQL inject attacks, but its a quick hack.
Kevin is right.
an example of his work around #1 in LinqPad. Need this (Object)s??DBNull.Value
string s = null;
//ExecuteCommand("insert into T(C1) values({0})", s); //Exception
SqlCommand cmd= new SqlCommand(){
CommandText = "insert into T(C1) values(#P0)",
Connection = new SqlConnection(this.Connection.ConnectionString),
};
//cmd.Parameters.AddWithValue("#P0", s); //SqlException
cmd.Parameters.AddWithValue("#P0", (Object)s??DBNull.Value);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Connection.Close();
Ts.OrderByDescending(t=>t.ID).Take(1).Dump();
have you tried assigning a value to those that are null? Meaning (pseudo):
If address is null then address = ""
or
If age is < 0 then age = 0
then add it to myList
or you could always use a Ternary operator:
name = name.Length < 1 ? "" : name;
age = age < 1 ? Int32.MinValue : age;
then add it to myList
Same issue for me. So stupid of MS not to fix that.
Here's my solution although I did not support all parameter types but ya get the idea. I stuck this in the DataContext class so it looks like it's built in to Linq :) .
public int ExecuteCommandEx(string sCommand, params object[] parameters)
{
object[] newParams = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
if (parameters[i] == null)
newParams[i] = "NULL";
else if (parameters[i] is System.Guid || parameters[i] is System.String || parameters[i] is System.DateTime)
newParams[i] = string.Format("'{0}'", parameters[i]);
else if (parameters[i] is System.Int32 || parameters[i] is System.Int16)
newParams[i] = string.Format("{0}", parameters[i]);
else
{
string sNotSupportedMsg = string.Format("Type of param {0} not currently supported.", parameters[i].GetType());
System.Diagnostics.Debug.Assert(false, sNotSupportedMsg);
}
}
return ExecuteCommand(string.Format(sCommand, newParams));
}
I use something like this (note I'm using the SO "IDE" so I can't, guarantee this will compile or work correctly but you'll get the idea)
public void InsertCostumer(string name, int age, string address)
{
List<object> myList = new List<object>();
myList.Add(name);
myList.Add(age);
myList.Add(address);
StringBuilder queryInsert = new StringBuilder();
queryInsert.Append("insert into Customers(name, age, address) values (");
int i = 0;
foreach (var param in myList.ToArray())
{
if (param == null)
{
queryInsert.Append("null, ");
myList.RemoveAt(i);
}
else
{
queryInsert.Append("{" + i + "}, ");
i++;
}
}
queryInsert.Remove(queryInsert.Length - 2, 2);
queryInsert.Append(")");
this.myDataContext.ExecuteCommand(queryInsert.ToString(), myList.ToArray());
}
I made a generic ParamArray Function to pass in the parms I normally would pass into the ExecuteCommand. Then have it pass back the uninterpretted SQL parms and a list of objects actually passed in.
Public Sub CommitRecords(ByVal InItems As List(Of Item)
Dim db As New DataContext(ConnectionString)
Try
For Each oItem In InItems
With oItem
Dim strParms As String = ""
Dim collParms = BuildExecuteCommandParms(strParms, .MapValue1, .MapValue2, .MapValue3, .MapValue4, .MapValue5, .MapValue6)
db.ExecuteCommand("Insert Into ItemTable (Value1, Value2, Value3, Value4, Value5, Value6)" & vbCrLf & _
"Values (" & strParms & ")", _
collParms.ToArray)
End With
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Public Function BuildExecuteCommandParms(ByRef strParms As String, ByVal ParamArray InParms As Object()) As List(Of Object)
Dim i As Integer = 0
Dim collOutParms As New List(Of Object)
For Each oParm In InParms
If i <> 0 Then strParms &= ", "
If oParm Is Nothing Then
strParms &= "NULL"
Else
strParms &= "{" & i & "}"
collOutParms.Add(oParm)
End If
i += 1
Next
Return collOutParms
End Function
I usually use this sort of thing, not ideal but it's gets it done if you're stuck
if (myObject != null)
{
foreach (var p in ct.GetType().GetProperties())
{
if (p.GetValue(myObject , null) == null)
{
if (p.PropertyType == typeof(string))
{
p.SetValue(myObject , "Empty", null);
}
if (p.PropertyType == typeof(int))
{
p.SetValue(myObject , 0, null);
}
if (p.PropertyType == typeof(int?))
{
p.SetValue(myObject , 0, null);
}
}
}
}
This makes sure each value in the object has a value before you use the parameters in ExecuteCommand. Again, not ideal, but it works.
I didn't like using string.format since (as the current selected answer to this question says) you're opening yourself to SQL injection.
So I solved the problem by iterating through the parameters and if the parameter is null, I add NULL as a string to the command text, if it it not null, I add a placeholder that will be replaced (similar to string.format) with values by ExecuteQuery (which does the SQL injection checks).
private static T ExecuteSingle<T>(string connectionString, string sprocName, params object[] sprocParameters)
where T : class
{
var commandText = sprocName;
if (sprocParameters.Length > 0)
{
// http://stackoverflow.com/questions/859985/linq-executecommand-doesnt-understand-nulls
int counter = 0;
var nulledPlaceholders = sprocParameters
.Select(x => x == null ? "NULL" : "{" + counter ++ + "}");
commandText += " " + string.Join(",", nulledPlaceholders);
sprocParameters = sprocParameters.Where(x => x != null).ToArray();
}
var connection = new SqlConnection(connectionString);
var dc = new DataContext(connection);
return dc.ExecuteQuery<T>(commandText, sprocParameters).SingleOrDefault();
}
internal static class DataContextExtensions
{
public static int ExecuteCommandEx(this DataContext context, string command, params object[] parameters)
{
if (context == null)
throw new ArgumentNullException("context");
if (parameters != null && parameters.Length > 0)
parameters = parameters.Select(p => p ?? "NULL").ToArray();
return context.ExecuteCommand(command, parameters);
}
}
why not use nullable values?
public void InsertCostumer(string? name, int? age, string? address)
{
List<object> myList = new List<object>();
myList.Add(name.GetValueOrDefault());
myList.Add(age.GetValueOrDefault());
myList.Add(address.GetValueOrDefault());
StringBuilder queryInsert = new StringBuilder();
queryInsert.Append("insert into Customers(name, address) values ({0}, {1}, {2})");
this.myDataContext.ExecuteCommand(queryInsert.ToString(), myList.ToArray());
}
In .NET, a null/nothing string does not evaluate to an empty string, i.e. "". If you want "", then that has to be the value of the string, or if you want to represent null/nothing in SQL, you have to manually write out "NULL" if your .NET string is in fact null/nothing.
All the execute command does, is execute a SQL query, provide by you, as a String. it doesn't do anything else special in terms of that SQL string.
So, for the Execute Command to work, you have to pass in a valid SQL string, you have to manually construct the string correctly.