I have a encoding problem with the Query of SQLite.Net. Everything works fine if i only use the column names in the SQL String, but if i write the SQL on my own, every special char like ä,ü,ö,ß will not be encoded correctly.
Here are two easy examples, one working, one not.
public class ass {
[PrimaryKey, AutoIncrement]
public int _id { get; set; }
[MaxLength(255)]
public string sortname { get; set; }
}
dbConn = new SQLiteConnection(new SQLitePlatformWinRT("testpasswort"),DB_PATH);
dbConn.CreateTable<ass>(SQLite.Net.Interop.CreateFlags.None);
//add a test entry with special chars
ass asss = new ass();
asss.sortname = "oe=öae=äszett=ß";
dbConn.Insert(asss);
//now select the test entry to an ass object
List<ass> getass = dbConn.Table<ass>().ToList<ass>();
//the list is filled and sortname = "oe=öae=äszett=ß"
//now fake a object with
List<ass> sqlass = dbConn.Query<ass>("SELECT 'oe=öae=äszett=ß' as sortname FROM ass").ToList<ass>();
//the List is filled and sortname = "oe=�ae=�szett=�"
I know the query is useless and the following will work:
List<ass> sqlass = dbConn.Query<ass>("SELECT sortname as FROM ass").ToList<ass>();
But the problem is, that the .Query funktion have a encoding issue, this will NOT work:
List<ass> sqlass = dbConn.Query<ass>("SELECT sortname FROM ass WHERE sortname LIKE '%ä%'").ToList<ass>();
But this will work:
List<ass> sqlass = dbConn.Query<ass>("SELECT sortname FROM ass).ToList<ass>().Where(v => v.sortname.Contains("ä"));
everytime i have any special char in the sqlcode it will not work, this is fatal for my needs, because i have a lot of replace(column,find,replace) statements and all of them failed if the find or replace String contains any ü,ö,ä [...]
Did anyone know how to sove this?
A possible solution would be to use #params instead of direct string request. And use the UTF-8 encoding pragma, which you can also use to check your existing database encoding. A helpful description for this issue can be found here.
Related
I am trying to find a specific string in a property of a class and replace it with another string if found. I tried various methods using Linq but I am not able to replace it. In debug mode, when I monitor the object again, the replace command hasn't worked. Please help. Including a sample example below.
class Tryreplace
{
public string ClubName { get; set; }
}
List<Tryreplace> tryreplaces = new List<Tryreplace>();
Tryreplace tryreplace = new Tryreplace { ClubName = "Manchester United FC" };
Tryreplace tryreplace2 = new Tryreplace { ClubName = "Arsenal FC" };
tryreplaces.Add(tryreplace);
tryreplaces.Add(tryreplace2);
Tried 2 ways below, both didn't work...
tryreplaces.ForEach(x => x.ClubName.Replace("Manchester", "Newcastle"));
List<Tryreplace> tryreplaces2 = tryreplaces.Select(x => { x.ClubName.Replace("Manchester", "Newcastle"); return x; }).ToList();
After both, I only see Manchester and not Newcastle.
I would like to see replaced string Newcastle in the objects and not Manchester. Please help!
Have an look at the official Documentation from the String.Replace() Method:
Returns a new string in which all occurrences of a specified string in
the current instance are replaced with another specified string.
So you will need to set the property as shown in the Example:
tryreplaces.ForEach(x => x.ClubName = x.ClubName.Replace("Manchester", "Newcastle"))
String.Replace() Docs from Microsoft
in C# (or most language) string are immutable, mean whenever you are making change to it, it will create another instance of string, but it will not change self variable itself.
Or simply if you want to replace part of the string you need to assign make to original variable.
string name = "Amyn";
name.Replace("A", "#");
Console.WriteLine(name); // it will be still Amyn
name = name.Replace("A", "#"); // its right way
Console.WriteLine(name); // it will display "#myn"
so in your code also you need to assign the variable back.
tryreplaces.ForEach(x => x.ClubName = x.ClubName.Replace("Manchester", "Newcastle"))
I have a machine generated excel file that has a few columns with the same name. e.g.:
A B C D
Group 1 Group 2
Period | Name Period | Name
And i got a DTO like this:
[ExcelColumn("Period")]
public string FirstPeriod { get; set; }
[ExcelColumn("Name")]
public string FirstName { get; set; }
[ExcelColumn("Period")]
public string SecondPeriod { get; set; }
[ExcelColumn("Name")]
public string SecondName { get; set; }
I use the following command to read the lines:
var excel = new ExcelQueryFactory(filePath);
excel.WorksheetRange<T>(beginCell, endColl + linesCount.ToString(), sheetIndex);
It reads the file just fine, but when i check the content of my DTO i saw that all the 'Second' properties have the same values of the 'First' ones.
This post was the closest thing that i found in my searches and i think the problem could be solved with something like this:
excel.AddMapping<MyDto>(x => x.FirstPeriod, "A");
excel.AddMapping<MyDto>(x => x.FirstName, "B");
excel.AddMapping<MyDto>(x => x.SecondPeriod, "C");
excel.AddMapping<MyDto>(x => x.SecondName, "D");
But i don't know how to get the excel column letters...
Obs: I got a few more code behind this but i don't think its relevant to the problem.
The problem that you're having is not possible to solve today with LinqToExcel because it wraps the OleDb functions and then they map properties based on columns names, so you lose the OleDb options like "FN" for specify columns (like "F1" for "A").
There's a issue on LinqToExcel github repo about this. https://github.com/paulyoder/LinqToExcel/issues/85
I recommend you to change the name of the columns to not duplicates names (e.g. Period1, Name1, Period2, Name2) if it's not possible to change because its machine generated, try change the header names in runtime.
Another option is to make more than one query in excel file, with ranges splitted your groups and then merging the results later.
var excel = new ExcelQueryFactory(filePath);
var group1 = excel.WorksheetRange<T>(A1, B + rowCount);
var group2 = excel.WorksheetRange<T>(C1, D + rowCount);
Edit: I'll work on a feature to try solve this problem in a elegant manner, so maybe in future you have a more flexible option to map columns and properties (if they accept my Pull Request)
I'm trying to add some csv elements to a list of Alimento, where Alimento is declared as:
namespace ContaCarboidrati
{
class Alimento
{
public virtual string Codice { get; set; }
public virtual string Descrizione { get; set; }
public virtual int Carboidrati { get; set; }
}
}
My csv looks something like this:
"C00, Pasta, 75".
Here's the method that should create the list from the csv:
private static List<Alimento> CreaListaAlimentiDaCsv()
{
List<Alimento> listaCsv = new List<Alimento>();
StreamReader sr = new StreamReader(#"C:\Users\Alex\Documents\RecordAlimenti.csv");
string abc = sr.ReadLine();
//listaCsv = abc.Split(",");
}
abc is "C00, Pasta, 75". I want to get a single element to add it to the list, or add all the 3 elements to the list, i thought that a single element is easier to made.
Sorry for my bad English
Thanks in advance
Alex
You are on the right track, but you cannot just create an Alimento of three strings, which is what you will get if you do abc.Split(","). You need to create a new Alimento object for each item (line) in the csv file and initialize each object correctly. Something like this:
var item = abc.Split(',');
listaCsv.Add(new Alimento() { Codice = item[0], Descrizione = item[1],
Carboidrati = int.Parse(item[2])};
Also, your csv seems to include spaces after the commas which you might want to get rid of. You could use string.Trim() to get rid of leading/trailing spaces. You also have to make sure the third item is actually an integer and take action if that is not the case (i.e. add some error handling).
As a side note, implementing a csv reader is not as trivial as one may think, but there are several free C# implementations out there. If you need something a bit more advanced than just reading a simple (and strictly one-line-per-item) csv, try one of these:
http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
http://www.filehelpers.com/
You can parse file with LINQ
var listaCsv = (from line in File.ReadAllLines("RecordAlimenti.csv")
let items = line.Split(',')
select new Alimento {
Codice = items[0],
Descrizione = items[1],
Carboidrati = Int32.Parse(items[2])
}).ToList();
You can parse it pretty easy assuming your data isn't bad.
private IEnumerable<Alimento> CreaListaAlimentiDaCsv(string fileName)
{
return File.Readlines(fileName) //#"C:\Users\Alex\Documents\RecordAlimenti.csv"
.Select(line => line.Split(',').Trim())
.Select(
values =>
new Alimento
{
Codice = value[0],
Descrizione = values[0],
Carboidrati = Convert.ToInt32(values[3])
});
}
You can also use Linq on the method such as
//Takes one line without iterating the entire file
CreaListaAlimentiDaCsv(#"C:\Users\Alex\Documents\RecordAlimenti.csv").Take(1);
//Skips the first line and takes the second line reading two lines total
CreaListaAlimentiDaCsv(#"C:\Users\Alex\Documents\RecordAlimenti.csv").Skip(1).Take(1);
I have a text file that looks like this:
1,Smith, 249.24, 6/10/2010
2,Johnson, 1332.23, 6/11/2010
3,Woods, 2214.22, 6/11/2010
1,Smith, 219.24, 6/11/2010
I need to be able to find the balance for a client on a given date.
I'm wondering if I should:
A. Start from the end and read each line into an Array, one at a time.
Check the last name index to see if it is the client we're looking for.
Then, display the balance index of the first match.
or
B. Use RegEx to find a match and display it.
I don't have much experience with RegEx, but I'll learn it if it's a no brainer in a situation like this.
I would recommend using the FileHelpers opensource project:
http://www.filehelpers.net/
Piece of cake:
Define your class:
[DelimitedRecord(",")]
public class Customer
{
public int CustId;
public string Name;
public decimal Balance;
[FieldConverter(ConverterKind.Date, "dd-MM-yyyy")]
public DateTime AddedDate;
}
Use it:
var engine = new FileHelperAsyncEngine<Customer>();
// Read
using(engine.BeginReadFile("TestIn.txt"))
{
// The engine is IEnumerable
foreach(Customer cust in engine)
{
// your code here
Console.WriteLine(cust.Name);
// your condition >> add balance
}
}
This looks like a pretty standard CSV type layout, which is easy enough to process. You can actually do it with ADO.Net and the Jet provider, but I think it is probably easier in the long run to process it yourself.
So first off, you want to process the actual text data. I assume it is reasonable to assume each record is seperated by some newline character, so you can utilize the ReadLine method to easily get each record:
StreamReader reader = new StreamReader("C:\Path\To\file.txt")
while(true)
{
var line = reader.ReadLine();
if(string.IsNullOrEmpty(line))
break;
// Process Line
}
And then to process each line, you can split the string on comma, and store the values into a data structure. So if you use a data structure like this:
public class MyData
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Balance { get; set; }
public DateTime Date { get; set; }
}
And you can process the line data with a method like this:
public MyData GetRecord(string line)
{
var fields = line.Split(',');
return new MyData()
{
Id = int.Parse(fields[0]),
Name = fields[1],
Balance = decimal.Parse(fields[2]),
Date = DateTime.Parse(fields[3])
};
}
Now, this is the simplest example, and doesn't account for cases where the fields may be empty, in which case you would either need to support NULL for those fields (using nullable types int?, decimal? and DateTime?), or define some default value that would be assigned to those values.
So once you have that you can store the collection of MyData objects in a list, and easily perform calculations based on that. So given your example of finding the balance on a given date you could do something like:
var data = customerDataList.First(d => d.Name == customerNameImLookingFor
&& d.Date == dateImLookingFor);
Where customerDataList is the collection of MyData objects read from the file, customerNameImLookingFor is a variable containing the customer's name, and customerDateImLookingFor is a variable containing the date.
I've used this technique to process data in text files in the past for files ranging from a couple records, to tens of thousands of records, and it works pretty well.
I think the cleanest way is to load the entire file into an array of custom objects and work with that. For 3 MB of data, this won't be a problem. If you wanted to do completely different search later, you could reuse most of the code. I would do it this way:
class Record
{
public int Id { get; protected set; }
public string Name { get; protected set; }
public decimal Balance { get; protected set; }
public DateTime Date { get; protected set; }
public Record (int id, string name, decimal balance, DateTime date)
{
Id = id;
Name = name;
Balance = balance;
Date = date;
}
}
…
Record[] records = from line in File.ReadAllLines(filename)
let fields = line.Split(',')
select new Record(
int.Parse(fields[0]),
fields[1],
decimal.Parse(fields[2]),
DateTime.Parse(fields[3])
).ToArray();
Record wantedRecord = records.Single
(r => r.Name = clientName && r.Date = givenDate);
Note that both your options will scan the file. That is fine if you only want to search in the file for 1 item.
If you need to search for multiple client/date combinations in the same file, you could parse the file into a Dictionary<string, Dictionary <date, decimal>> first.
A direct answer: for a one-off, a RegEx will probably be faster.
If you're just reading it I'd consider reading in the whole file in memory using StreamReader.ReadToEnd and then treating it as one long string to search through and when you find a record you want to look at just look for the previous and next line break and then you have the transaction row you want.
If it's on a server or the file can be refreshed all the time this might not be a good solution though.
If it's all well-formatted CSV like this then I'd use something like the Microsoft.VisualBasic.TextFieldParser class or the Fast CSV class over on code project to read it all in.
The data type is a little tricky because I imagine not every client has a record for every day. That means you can't just have a nested dictionary for your looksup. Instead, you want to "index" by name first and then date, but the form of the date record is a little different. I think I'd go for something like this as I read in each record:
Dictionary<string, SortedList<DateTime, double>>
hey, hey, hey!!! why not do it with this great project on codeproject Linq to CSV, way cool!
rock solid
I am at the end of my knowledge and googled for the answer too but no luck :/
Week ago everything worked well.
I did a revert on the repository, recreated the tableadapter etc... nothing helped.
When I try to save in my application I get an SystemInvalidCastException at this point:
PersonListDataSet.cs:
partial class P_GroupTableAdapter
{
public int Update(PersonListDataSet.P_GroupDataTable dataTable, string userId)
{
this.Adapter.InsertCommand.Parameters["#userId"].Value = userId;
this.Adapter.DeleteCommand.Parameters["#userId"].Value = userId;
this.Adapter.UpdateCommand.Parameters["#userId"].Value = userId;
return this.Update(dataTable); **<-- Exception occurs here**
}
}
Everything is stuck here because a Guid - and I checked the datatable preview with the magnifier tool its really a true Guid in the column of the datatable - can not be converted to a string ??? How can that happen?
It's the other way around. Your userId is a string and you need a GUID value for your parameters:
Parameters["#userId"].Value = new Guid(userId);
Provided UserId is in one of the supported formats for a GUID. The constructor supports many formats.
Edit, based on comments below:
It turns out that you are asking how to run a select statement like:
SELECT ....
WHERE '{BB6DFF45-FDA7-4155-86D0-0CBF129A9104}' = `domainname\\jondoe`
I think you should re-check your datamodel and find a solution.
Have you tried:
this.Adapter.InsertCommand.Parameters["#userId"].Value = new Guid(userId);
this.Adapter.DeleteCommand.Parameters["#userId"].Value = new Guid(userId);
this.Adapter.UpdateCommand.Parameters["#userId"].Value = new Guid(userId);
Hope it helps!!!