System.Data.SqlClient.SqlException: 'Incorrect syntax near ') in C# - c#

I can't find the error in the code but it showing me.
System.Data.SqlClient.SqlException: 'Incorrect syntax near ')
My code is here:
private void ShowChart()
{
string UserID = "";
for (int Counter = 0; Counter < UID.Count - 1; Counter++)
{
UserID += UID[Counter].ToString() + ",";
}
UserID = UserID.Substring(0, UserID.Length);
string[] ListFamily = { };
int[] ListTime = { };
var Query = Database.Database.SqlQuery<Vw_ShowChartInfo>("Select * From Vw_ShowChartInfo Where UserID In (" + UserID + ")").ToList();
for (int I = 0; I < Query.Count; I++)
{
Family.Add(Query[I].FullName.ToString());
Time.Add(Convert.ToInt32(Query[I].TotalTime));
ListFamily = Family.ToArray();
ListTime = Time.ToArray();
}
this.Chart.Series.Clear();
this.Chart.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.Pastel;
this.Chart.Titles.Add("نمودار کارکرد پرسنل");
for (int II = 0; II < ListFamily.Length; II++)
{
Series series = this.Chart.Series.Add(ListFamily[II] + "-" + Query[II].TotalTime);
series.Points.Add(ListTime[II]);
}
}

I think your problem might be this line:
UserID = UserID.Substring(0, UserID.Length);
The string you are generating contains a comma at the end. It looks like you are attempting to trim the comma with that line but you are simply selecting the same string again. Use this instead:
UserID = UserID.Substring(0, UserID.Length - 1);
Also, the assumption is your user ids are numeric. Otherwise, you would need to surround them with single quotes.
That being said, it's a terrible idea to concatenate strings this way as it leaves you open to SQL injection attacks. Consider a different approach.

Related

C#: Need to split a string into a string[] and keeping the delimiter (also a string) at the beginning of the string

I think I am too dumb to solve this problem...
I have some formulas which need to be "translated" from one syntax to another.
Let's say I have a formula that goes like that (it's a simple one, others have many "Ceilings" in it):
string formulaString = "If([Param1] = 0, 1, Ceiling([Param2] / 0.55) * [Param3])";
I need to replace "Ceiling()" with "Ceiling(; 1)" (basically, insert "; 1" before the ")").
My attempt is to split the fomulaString at "Ceiling(" so I am able to iterate through the string array and insert my string at the correct index (counting every "(" and ")" to get the right index)
What I have so far:
//splits correct, but loses "CEILING("
string[] parts = formulaString.Split(new[] { "CEILING(" }, StringSplitOptions.None);
//splits almost correct, "CEILING(" is in another group
string[] parts = Regex.Split(formulaString, #"(CEILING\()");
//splits almost every letter
string[] parts = Regex.Split(formulaString, #"(?=[(CEILING\()])");
When everything is done, I concat the string so I have my complete formula again.
What do I have to set as Regex pattern to achieve this sample? (Or any other method that will help me)
part1 = "If([Param1] = 0, 1, ";
part2 = "Ceiling([Param2] / 0.55) * [Param3])";
//part3 = next "CEILING(" in a longer formula and so on...
As I mention in a comment, you almost got it: (?=Ceiling). This is incomplete for your use case unfortunately.
I need to replace "Ceiling()" with "Ceiling(; 1)" (basically, insert "; 1" before the ")").
Depending on your regex engine (for example JS) this works:
string[] parts = Regex.Split(formulaString, #"(?<=Ceiling\([^)]*(?=\)))");
string modifiedFormula = String.join("; 1", parts);
The regex
(?<=Ceiling\([^)]*(?=\)))
(?<= ) Positive lookbehind
Ceiling\( Search for literal "Ceiling("
[^)] Match any char which is not ")" ..
* .. 0 or more times
(?=\)) Positive lookahead for ")", effectively making us stop before the ")"
This regex is a zero-assertion, therefore nothing is lost and it will cut your strings before the last ")" in every "Ceiling()".
This solution would break whenever you have nested "Ceiling()". Then your only solution would be writing your own parser for the same reasons why you can't parse markup with regex.
Regex.Replace(formulaString, #"(?<=Ceiling\()(.*?)(?=\))","$1; 1");
Note: This will not work for nested "Ceilings", but it does for Ceiling(), It will also not work fir Ceiling(AnotherFunc(x)). For that you need something like:
Regex.Replace(formulaString, #"(?<=Ceiling\()((.*\((?>[^()]+|(?1))*\))*|[^\)]*)(\))","$1; 1$3");
but I could not get that to work with .NET, only in JavaScript.
This is my solution:
private string ConvertCeiling(string formula)
{
int ceilingsCount = formula.CountOccurences("Ceiling(");
int startIndex = 0;
int bracketCounter;
for (int i = 0; i < ceilingsCount; i++)
{
startIndex = formula.IndexOf("Ceiling(", startIndex);
bracketCounter = 0;
for (int j = 0; j < formula.Length; j++)
{
if (j < startIndex) continue;
var c = formula[j];
if (c == '(')
{
bracketCounter++;
}
if (c == ')')
{
bracketCounter--;
if (bracketCounter == 0)
{
// found end
formula = formula.Insert(j, "; 1");
startIndex++;
break;
}
}
}
}
return formula;
}
And CountOccurence:
public static int CountOccurences(this string value, string parameter)
{
int counter = 0;
int startIndex = 0;
int indexOfCeiling;
do
{
indexOfCeiling = value.IndexOf(parameter, startIndex);
if (indexOfCeiling < 0)
{
break;
}
else
{
startIndex = indexOfCeiling + 1;
counter++;
}
} while (true);
return counter;
}

How to delete a specific record (fixed length) includes data from a .txt file?

I am new in C# and I am making project but I can't make this delete part ..
If I save my data in .txt file in one line, but contain many fixed length record with no delimiter, if each record has fixed length and each field has fixed length and saved in file like this
1ahly2zamalek
how do I delete, for example the record 2zamalek from line with entering to the program id=2?
public team()
{
Team_ID_Len = 5;
Team_Name_Len = 10;
Team_Rec_Len = 15; ;
Team_ID = new char[Team_ID_Len];
Team_Name = new char[Team_Name_Len];
}
Sounds like you're looking for Substring. Give it a start (length of record * how many), and the length (length of record).
Actually, you might want to create the string as string s = part1+part2 where part1 is the substring from 0 till the start of the record, and part2 is the start of the NEXT record, until the end.
Then just save it.
Your number is your delimiter, split with a char array
using System;
using System;
public static class Program
{
public static void Main()
{
string words = "1sdklfjlsdf2lksjdf3sfd4sfd5fsd6fsd7fsd8fsd9sfd10aslkdfj11jklh12hjk";
int deleteRecordId = 11;
string [] split = words.Split(new Char [] {'1', '2','3','4','5','6','7','8','9','0'});
string newString = "";
int j = 0;
for( int i = 0; i < split.Length; i++)
{
if ( j == deleteRecordId)
{
//ignore this record
Console.WriteLine("ignore i = " + i);
j++;
}
else
{
Console.WriteLine("i = " + i);
if(!( split[i] == ""))
{
newString += j + split[i];
j++;
}
}
}
Console.WriteLine(newString);
}
}
then WriteAll to the file

Adding parameters in stored procedure using c#

I want to automatically add parameters based on the input of control numbers.
the following code will give me sp_INSERT #COL5, sp_INSERT #COL4, so on...
control = 5;
while(1<=control)
column = '#COL'
string setValues = "sp_INSERT'" + column + control + "';"
control = control - 1;
What I want to achieve is sp_INSERT #COL5, #COL4, #COL3, so on...
Just... loop?
int control = 5;
string colPrefix = "#COL";
var sql = new StringBuilder("sp_INSERT ").Append(colPrefix).Append(control);
// note first item has different format due to comma
for(int i = control - 1; i > 0; i--)
{
sql.Append(", ").Append(colPrefix).Append(i);
}
sql.Append(';');
string s = sql.ToString();
Simple loop, not a complete solution, but it might help...
string myString = "INSERT ";
for (int i = 5; i > 0; i--)
myString = string.Format("{0} #COL{1}, ", myString, i);

Logical error in simple acronym generator

I have some kind of logical error in my program. Whenever I enter a phrase with 1 letter I get a ArgumentOutOfRange Exception, and whenever I enter a multiple letter word the textbox clears, displays "Apple" (the first value in my array) and does nothing else. Can anybody see the logical error in this?
string[] d = { "Apple", "Bass", "Cat", "Dog", "Ear", "Flamingo", "Gear", "Hat", "Infidel", "Jackrabbit", "Kangaroo", "Lathargic", "Monkey", "Nude", "Ozzymandis", "Python", "Queen", "Rat", "Sarcastic", "Tungston", "Urine", "Virginia", "Wool", "Xylophone", "Yo-yo", "Zebra", " " };
string var;
int len = 0;
private void button1_Click(object sender, EventArgs e)
{
var = textBox2.Text;
textBox1.Text = "";
for (int y = 0; y < var.Length; y++)
{
for (int x = 0; x < d.Length; x++)
{
if (d[x].ToUpper().Substring(0, 0) == var.ToUpper().Substring(len, len))
{
len = len + 1;
textBox1.Text = textBox1.Text + "\n" + d[x];
}
}
}
}
Substring(0, 0) is really pointless. This will always be an empty string.
Substring(len, len) also is a bad idea, because it will return a string of length len starting at index len. This is where you get your exception.
I assume, what you really want is the second parameter to be 1 in both cases. And that can be further simplified to an access via index:
d[x].ToUpper()[0] == var.ToUpper()[len]
You can do the same quite easily using LINQ:
private void button1_Click(object sender, EventArgs e)
{
var dict = d.ToDictionary(x => x.First(), x => x);
textBox1.Text = string.Join(Environment.NewLine, textBox2.Text.Select(x => dict[char.ToUpper(x)]));
}
To do it without LINQ I would suggest following:
for (int y = 0; y < input.Length; y++)
{
for (int x = 0; x < d.Length; x++)
{
if (char.ToUpper(d[x][0]) == char.ToUpper(input[y]))
{
result = result + "\n" + d[x];
}
}
}
Changes are:
you don't need len variable. Use y instead.
you don't need whole string uppercased. Use char.ToUpper static method instead.
you don't need string.Substring method. Use indexers instead.
This line explains the behavior.
if (d[x].ToUpper().Substring(0, 0) == var.ToUpper().Substring(len, len))
Second parameter of substring is string length. So on the left you always have an empty string. On the right you also have empty string when len==0 (that's why your code always picks Apple).
After that you change len, and repeat the loop. Then expression on the right is var.Substring(1,1) which gives you the error if your string is 1 character long. Because this reads - 1 symbol starting with 1 (which is second character of the string)
Apart from that, the purpose of the code is complete mystery, so there are definitely other errors.

C# Best way to get folder depth for a given path?

I'm working on something that requires traversing through the file system and for any given path, I need to know how 'deep' I am in the folder structure. Here's what I'm currently using:
int folderDepth = 0;
string tmpPath = startPath;
while (Directory.GetParent(tmpPath) != null)
{
folderDepth++;
tmpPath = Directory.GetParent(tmpPath).FullName;
}
return folderDepth;
This works but I suspect there's a better/faster way? Much obliged for any feedback.
Off the top of my head:
Directory.GetFullPath().Split("\\").Length;
I'm more than late on this but I wanted to point out Paul Sonier's answer is probably the shortest but should be:
Path.GetFullPath(tmpPath).Split(Path.DirectorySeparatorChar).Length;
I'm always a fan the recursive solutions. Inefficient, but fun!
public static int FolderDepth(string path)
{
if (string.IsNullOrEmpty(path))
return 0;
DirectoryInfo parent = Directory.GetParent(path);
if (parent == null)
return 1;
return FolderDepth(parent.FullName) + 1;
}
I love the Lisp code written in C#!
Here's another recursive version that I like even better, and is probably more efficient:
public static int FolderDepth(string path)
{
if (string.IsNullOrEmpty(path))
return 0;
return FolderDepth(new DirectoryInfo(path));
}
public static int FolderDepth(DirectoryInfo directory)
{
if (directory == null)
return 0;
return FolderDepth(directory.Parent) + 1;
}
Good times, good times...
If you use the members of the Path class, you can cope with localizations of the path separation character and other path-related caveats. The following code provides the depth (including the root). It's not robust to bad strings and such, but it's a start for you.
int depth = 0;
do
{
path = Path.GetDirectoryName(path);
Console.WriteLine(path);
++depth;
} while (!string.IsNullOrEmpty(path));
Console.WriteLine("Depth = " + depth.ToString());
Assuming your path has already been vetted for being valid, in .NET 3.5 you could also use LINQ to do it in 1 line of code...
Console.WriteLine(#"C:\Folder1\Folder2\Folder3\Folder4\MyFile.txt".Where(c
=> c = #"\").Count);
If the directory has a backslash at the end, you get a different answer than when it doesn't. Here's a robust solution to the problem.
string pathString = "C:\\temp\\"
var rootFolderDepth = pathString.Split(Path.DirectorySeparatorChar).Where(i => i.Length > 0).Count();
This returns a path length of 2. If you do it without the where statement, you get a path length of 3 or a path length of 2 if you omit the last separator character.
Maybe someone need also some performance testing...
double linqCountTime = 0;
double stringSplitTime = 0;
double stringSplitRemEmptyTime = 0;
int linqCountFind = 0;
int stringSplitFind = 0;
int stringSplitRemEmptyFind = 0;
string pth = #"D:\dir 1\complicated dir 2\more complicated dir 3\much more complicated dir 4\only dir\another complicated dir\dummy\dummy.dummy.45682\";
//Heat Up
DateTime dt = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
linqCountFind = pth.Count(c => c == '\\');
}
_= DateTime.Now.Subtract(dt).TotalMilliseconds;
dt = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
stringSplitFind = pth.Split('\\').Length;
}
_ = DateTime.Now.Subtract(dt).TotalMilliseconds;
dt = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
stringSplitRemEmptyFind = pth.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
_ = DateTime.Now.Subtract(dt).TotalMilliseconds;
dt = DateTime.Now;
//Testing
dt = DateTime.Now;
for (int i = 0; i < 1000000; i++)
{
linqCountFind = pth.Count(c => c == '\\');
}
linqCountTime = DateTime.Now.Subtract(dt).TotalMilliseconds; //linq.Count: 1390 ms
dt = DateTime.Now;
for (int i = 0; i < 1000000; i++)
{
stringSplitFind = pth.Split('\\').Length-1;
}
stringSplitTime = DateTime.Now.Subtract(dt).TotalMilliseconds; //string.Split: 715 ms
dt = DateTime.Now;
for (int i = 0; i < 1000000; i++)
{
stringSplitRemEmptyFind = pth.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
stringSplitRemEmptyTime = DateTime.Now.Subtract(dt).TotalMilliseconds; // string.Split with RemoveEmptyEntries option: 720 ms
string linqCount = "linqCount - Find: "+ linqCountFind + "; Time: "+ linqCountTime.ToString("F0") +" ms"+ Environment.NewLine;
string stringSplit = "stringSplit - Find: " + stringSplitFind + "; Time: " + stringSplitTime.ToString("F0") + " ms" + Environment.NewLine;
string stringSplitRemEmpty = "stringSplitRemEmpty - Find: " + stringSplitRemEmptyFind + "; Time: " + stringSplitRemEmptyTime.ToString("F0") + " ms" + Environment.NewLine;
MessageBox.Show(linqCount + stringSplit + stringSplitRemEmpty);
// Results:
// linqCount - Find: 9; Time: 1390 ms
// stringSplit - Find: 9; Time: 715 ms
// stringSplitRemEmpty - Find: 9; Time: 720 ms
So, for most cases, the best is string.split() (see results in code comments).
string.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries) is safer for path.
And for more complicated cases see:
https://cc.davelozinski.com/c-sharp/fastest-way-count-number-times-character-occurs-string
and
https://cc.davelozinski.com/c-sharp/c-net-fastest-way-count-substring-occurrences-string

Categories