using MySQL to create JSON with C# and JSON.Net - c#

I am having quite a lot of trouble trying to find a tutorial that will tech me how to use MySqlReader (with MySQL) to insert or receive data through a class object. The construtor is shown as follow.
Where I have used http://json2csharp.com/ to create these class I know how to serialize/deserialize a class object into JSON. my problem really lies in getting the data from a lot of different table in and out of the database connector via MySqlDataReader into a class object.
I don't know if this matter but I am using .Net 2.0 with C# 3.0 (visual studio 2010). Thank you in advance for any comment or reply.
public class Boardingzone
{
public string zone { get; set; }
public string time { get; set; }
}
public class Serial
{
public string rsn { get; set; }
public List<Boardingzone> boardingzone { get; set; }
}
public class RootObject
{
public string name { get; set; }
public List<Serial> serial { get; set; }
}
This is what i have tried so far
string sql = "SELECT Route.RName, RouteSerial.RSN, Stop.StopName, TimeTable.BoardTime FROM TimeTable INNER JOIN Stop ON TimeTable.StopID = Stop.StopID INNER JOIN RouteSerial ON TimeTable.RSN = RouteSerial.RSN INNER JOIN Route ON RouteSerial.RID = Route.RID";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
ArrayList name = new ArrayList();
ArrayList rsn = new ArrayList();
ArrayList zone = new ArrayList();
ArrayList time = new ArrayList();
while (rdr.Read()){
string val = "";
val = rdr.GetValue(0).ToString();
name.Add(val);
val = rdr.GetValue(1).ToString();
rsn.Add(val);
val = rdr.GetValue(2).ToString();
zone.Add(val);
val = rdr.GetValue(3).ToString();
time.Add(val);
}
rdr.Close();
conn.Close();

you are almost doing it right. without going into too much detail, you need to instantiate the classes you want to populate:
var currentRoot = null;
var rootObjects = new List<RootObject>();
while (rdr.Read()){
string name= rdr.GetValue(0).ToString();
string serial = rdr.GetValue(1).ToString();
string bz = rdr.GetValue(2).ToString(); <-- made this up
if( currentRoot == null || currentRoot.name != name )
{
if( currentRoot != null ){
rootObjects.Add(currentRoot);
}
currentRoot = new RootObject();
currentRoot.name = name;
}
currentRoot.serials.Add(new Serial(){zone = bz});
... instantiate other classes
}
rdr.Close();
foreach( var rootObj in rootObjects) doSomethingWithRootObj(rootObj);
hope it helps.

I am not sure what the purpose of populating the ArrayList is, you will have to somehow populate your Model from your arraylist either by mapping or manually.
For the simple case why can you not just populate your model here?
One good approach to this would be to keep your Model in a separate assembly, your DAL can then reference this assembly in order to populate the appropriate classes.
Better still would be if you could expose your model as interfaces then the DAL need only use those interfaces and can have its own implementation - not sure if this is possible with the serialization method you use.

Related

WCF, Xamarin - CS0029 Cannot implicitly convert to System.Collections.ObjectModel.ObservableCollection

Having a convertion issue between my WCF service returned ObservableCollection and handling the result to fill a ListView.
So in both WCF and PCL Projects i have this Temoignage.cs in Model folder
public class Temoignage
{
public string Nom { get; set; }
public string Prenom { get; set; }
public int Note { get; set; }
public string Texte { get; set; }
}
The WCF service returning this
public ObservableCollection<Temoignage> GetTemoignage()
{
ObservableCollection<Temoignage> TemoignageList = new ObservableCollection<Temoignage>();
con.Open();
SqlCommand cmd = new SqlCommand("Select U.nom, U.Prenom, T.note, T.texte from dbo.Temoignages T inner join Users U on U.id = T.iduser where T.validation = 1;", con);
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
while (reader.Read())
{
Temoignage temoignage = new Temoignage
{
Nom = reader.GetString(0),
Prenom = reader.GetString(1),
Note = reader.GetInt32(2),
Texte = reader.GetString(3)
};
TemoignageList.Add(temoignage);
}
return TemoignageList;
}
And the ViewModel which receive it
public ObservableCollection<Temoignage> TemoignagesList { get; set; }
....
public void Temoignages()
{
BasicHttpBinding binding = CreateBasicHttp();
this.client1 = new BienEtreServiceClient(binding, EndPoint);
this.instance = ((IBienEtreService)client1.InnerChannel);
client1.GetTemoignageCompleted += ClientOnGetTemoignageCompleted;
client1.GetTemoignageAsync();
}
public void ClientOnGetTemoignageCompleted(object sender, GetTemoignageCompletedEventArgs e)
{ // The problems starts here
ObservableCollection<Temoignage> TemTest = e.Result;
foreach (Temoignage item in TemTest)
{
TemoignagesList.Add(item);
}
}
I thought i could, in ClientOnGetTemoignageCompleted, just take the ObservableCollection i got from WCF and add the elements in my already existing TemoignagesList (which is binded to XAML).
But nope. Even if the Models contains same elements in both projects.
e.Result containt elements i need, i just don't know how to read them.
equals to this when ClientOnGetTemoignageCompleted is executed
Am i missing an important point?
Thanks for help
I think i found it myself, using the models of my wcf service and not the client ones
//using BienEtre.Models;
using BienEtreWcfService;
Now this works and add elements to the list.
public void ClientOnGetTemoignageCompleted(object sender, GetTemoignageCompletedEventArgs e)
{
foreach (Temoignage item in e.Result)
{
TemoignagesList.Add(item);
}
}
Not sure i understood, but it works!
I'm also using List instead of ObservableCollection.

c# how to decide whether to add to sub-list or start new one

I have an sql query that provides me my data where I sometimes have lines that should be clustered (the data is aligned with an order by). The data is grouped by the field CAPName. Going through those rows line by line, I need to decide whether a new list should be initiated (content of CAPName differs to previous itteration), or whether the (already) initated list (from the previous iteration) should be added, too.
My pain lays with the location of the declaration of the relatedCapabilitySystem list.
I wanted to declare it within the if statement (Because, as I stated I need to decide whether the list from the previous iteration should be added too, or whether it should start a new list), but I can't as the compiler throws an exception, as the RLCapSys.Add(rCs); is non-existing in this content (which is only theoretically true). I understand why the compiler throws this exception. But if I declare the list on a "higher" level, than I always have a new list, which I don't want in the case that the item should be added to the list defined in the iteration(s) (1 or more) before
So what I want to achieve is, generate the list RLCapSys and add to it, in case the previous iteration contains the same CAPName (for clustering), otherwise create a new list.
SqlCommand cmdDetail = new SqlCommand(SQL_SubSytemsToCapability, DBConDetail);
SqlDataReader rdrDetail = cmdDetail.ExecuteReader();
List<relatedCapility> RLCaps = new List<relatedCapility>();
string lastCapShown = null;
while (rdrDetail.Read())
{
List<relatedCapabilitySystem> RLCapSys = new List<relatedCapabilitySystem>();
if (lastCapShown != rdrDetail["CAPName"].ToString())
{
//List<relatedCapabilitySystem> RLCapSys2 = new List<relatedCapabilitySystem>();
relatedCapility rC = new relatedCapility
{
Capability = rdrDetail["CAPName"].ToString(),
systemsRelated = RLCapSys,
};
RLCaps.Add(rC);
}
relatedCapabilitySystem rCs = new relatedCapabilitySystem
{
system = rdrDetail["name"].ToString(),
start = rdrDetail["SysStart"].ToString(),
end = rdrDetail["SysEnd"].ToString(),
};
RLCapSys.Add(rCs);
// method to compare the last related Capability shown create a new related Capabilty entry or add to the existing releated Capabilty related system list
lastCapShown = rdrDetail["CAPName"].ToString();
}
DBConDetail.Close();
and for reason of completness (but I think it is not needed here):
internal class CapabilitiesC
{
public List<Capability>Capabilities{ get;set;}
}
public class Capability
{
public string name { get; internal set; }
public string tower { get; internal set; }
public string color { get; internal set; }
public List<relatedCapility> related { get; set; }
}
public class relatedCapility
{
public string Capability { get; set; }
public List<relatedCapabilitySystem> systemsRelated { get; set; }
}
public class relatedCapabilitySystem
{
public string system { get; set; }
public string start { get; set; }
public string end { get; set; }
}
The purpose of your code is to take the input data and group it by capability. However, that is not immediately obvious. You can change your code to use LINQ so it becomes easier to understand and in the process solving your problem.
First you need a type to represent a record in your database. For lack of better name I will use Record:
class Record
{
public string System { get; set; }
public string Start { get; set; }
public string End { get; set; }
public string Capabilty { get; set; }
}
You can then create an iterator block to return all the records from the database (using an OR mapper like Entity Framework avoids most of this code and you can even shift some of the work from your computer to the database server):
IEnumerable<Record> GetRecords()
{
// Code to create connection and command (preferably in a using statement)
SqlDataReader rdrDetail = cmdDetail.ExecuteReader();
while (rdrDetail.Read())
{
yield return new Record {
System = rdrDetail["name"].ToString(),
Start = rdrDetail["SysStart"].ToString(),
End = rdrDetail["SysEnd"].ToString(),
Capability = rdrDetail["CAPName"].ToString()
};
}
// Close connection (proper using statement will do this)
}
Finally, you can use LINQ to perform the grouping:
var RLCaps = GetRecords()
.GroupBy(
record => record.Capability,
(capability, records) => new relatedCapility
{
Capability = capability ,
systemsRelated = records
.Select(record => new relatedCapabilitySystem
{
system = record.System,
start = record.Start,
end = record.End
})
.ToList()
})
.ToList();
Why not just assign it as NULL. The pattern would be
List<> myList = null;
if(condition)
{
myList = new List<>();
}
else
{
myList = previousList;
}
myList.Add();
previousList = myList;
I've got it working now. Thx everyone for your help. #martin, thx for your solution, you have put quite some effort into this, but that would have required for me to completely re-write my code. I am sure your approach would work and will be my next approach should I have a similar problem again.
It was a combination of the other answers that helped me figure it out. Let me show you what I ended up with:
SqlCommand cmdDetail = new SqlCommand(SQL_SubSytemsToCapability, DBConDetail);
SqlDataReader rdrDetail = cmdDetail.ExecuteReader();
List<relatedCapility> RLCaps = new List<relatedCapility>();
List<relatedCapabilitySystem> RLCapSys = new List<relatedCapabilitySystem>();
string lastCapShown = null;
while (rdrDetail.Read())
{
if (lastCapShown != rdrDetail["CAPName"].ToString())
{
RLCapSys = relatedCapabilitySystemList();
relatedCapility rC = new relatedCapility
{
Capability = rdrDetail["CAPName"].ToString(),
systemsRelated = RLCapSys,
};
RLCaps.Add(rC);
}
relatedCapabilitySystem rCs = new relatedCapabilitySystem
{
system = rdrDetail["name"].ToString(),
start = rdrDetail["SysStart"].ToString(),
end = rdrDetail["SysEnd"].ToString(),
};
RLCapSys.Add(rCs);
// method to compare the last related Capability shown create a new related Capabilty entry or add to the existing releated Capabilty related system list
lastCapShown = rdrDetail["CAPName"].ToString();
}
DBConDetail.Close();
So that's the section already shown bevor including my changes. Plus I added this:
private List<relatedCapabilitySystem> relatedCapabilitySystemList()
{
List<relatedCapabilitySystem> RLCapSys = new List<relatedCapabilitySystem>();
return RLCapSys;
}
Now I have new list reference everytime the CapName changes that is then added to the "higher" list. Before I had the issue of the very same list repeatedly assigned rather than a fresh one started. So thx again for your effort.

C# access List after return

I'm a noob with C# but I'm trying to create a simple code for connecting to my mysql database (most of the code I got from google). So I have this part where something from the database is selected and stored in a list. Now I want to access this from another class but I have no idea how to do that and I couldn't find the answer on google either (this thread also didn't worked for me: Access List from another class) so can anyone please help me?
Here's the particular code:
public List<string>[] Select()
{
string query = "SELECT * FROM users";
//Create a list to store the result
List<string>[] list = new List<string>[3];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["id"] + "");
list[1].Add(dataReader["test"] + "");
list[2].Add(dataReader["balance"] + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
else
{
return list;
}
}
Class containing your original method:
public class YourClass
{
public List<string>[] Select()
{
string query = "SELECT * FROM users";
//Create a list to store the result
List<string>[] list = new List<string>[3];
///
/// you original implementation here
///
}
}
Here Class where you use your method:
public class UsingClass
{
private YourClass _yourClass;
public UsingClass()
{
_yourClass = new YourClass();
}
private void SomeUsingMethod()
{
List<string>[] list = _yourClass.Select();
}
}
Seriously I think the way you've structured the data here, is strange.
You're creating an array of a objects, where the object is a List of string:
List<string>[] list = new List<string>[3];
You want to be thinking in objects; create a class that represents the data; in this case User. Something like this:
public class User
{
public string Id { get; set; }
public string Test { get; set; }
public string Balance { get; set; }
}
So personally I'd do the following:
Create a class that represents each user record.
Create a variable to hold a list of users.
Read from MySql and assign each record to a new User object.
Add the user to the list.
Return the list.
Change the return type of your Select method to be List<User> like this:
public List<User> Select() {
Then amend the rest of the method to create and return list of users.
public List<User> Select() {
List<User> list = new List<User>();
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
User user = new User();
user.Id = dataReader["id"].toString();
user.Test = dataReader["test"].toString();
user.Balance = dataReader["balance"].toString();
list.Add(user);
}
dataReader.Close();
this.CloseConnection();
}
return list;
}
Then you can use your list something like this:
ClassThatContainsSelectMethod yourDBObject = new ClassThatContainsSelectMethod();
List<User> users = yourDBObject.Select();
foreach (User user in users)
{
Console.WriteLine(user.Id, user.Test, user.Balance);
}
This code of course could be better structured with factories and error/null checks but it should get you going in the right direction.
There are multiple ways to share data from classes.One of them is defining a property for the desired list and then accsess it. Lets say you have class data
class DataString
{
private string data = "data";
public string Data
{
get { return data}
set { data = value }
}
}
and
class Program
{
static void Main()
{
DataString dataStr = new DataString();
// Assigning the dataStr property causes the 'set' accessor to be called.
dataStr.Data = "some string";
// Evaluating the Hours property causes the 'get' accessor to be called.
System.Console.WriteLine(dataStr.Data); //this will display "some string"
}
}
You could the same way create a list class with your desired functions and variables and modiffy them with methods and access them with properties.

Learning to use Dapper: throws Invalid cast error

VS2013 c# windows form.
I am learning Dapper and this is my 1st shot at it:
I have a simple class:
public class R
{
public int RID { get; set; }
public int RType { get; set; }
public string CC { get; set; }
public string RI { get; set; }
.
.
.
}
private void _setR(string rID)
{
int r_ID = Convert.ToInt16(requestID);
MY_R = new R();
SqlConnection c = new SqlConnection(Connection string);
c.Open();
var v= c.Query<R>("select RID, RType, CC, RI, .,.,., " +
"from Db_View_R where RID=#r_ID",
new { #r_ID = r_ID }) ;
c.Close();
MY_R = (R)v ; <--------- Invalid cast error here
}
The query is simple: a few columns from a view. Returns only 1 row. Not sure what am I missing here.
Thanks in advance
Extension method Query<T> returns IEnumerable<T>. So you definitely can't assign value of type IEnumerable<T> to variable of type T. You should take only one item from sequence:
MY_R = v.FirstOrDefault(); // or First, Single, SingleOrDefault
Actually with improved naming your code should look like:
var sql = "SELECT RID, RType, CC, RI FROM Db_View_R where RID = #id";
using(var conn = new SqlConnection(ConnectionString))
{
MY_R = conn.Query<R>(sql, new { id = Convert.ToInt16(requestID) })
.FirstOrDefault();
}
I still don't like names like R (it probably should be Request) but its already much more readable and safe (you should wrap connection usage in using statement).
use SingleOrDefault()
var v= c.Query<R>("select RID, RType, CC, RI, .,.,., " +
"from Db_View_R where RID=#r_ID",
new { #r_ID = r_ID }).SingleOrDefault();

Changing XML List name for String after a webservice invoke

ok with the suggestion now the output is
<picture>11000covcl_2.jpg</picture>
<picture>11000covcl_3.jpg</picture>
<picture>11000covcl_4.jpg</picture>
I would like to look like this
<picture_list>
<picture>....</picture>
</picture_list>
this is c# code im using
sqlCommand = "{CALL getPictureList(?)}";
sqlParamList = new String[,] { { "#ProductID", prodID } };
OdbcDataReader pDataReader = null;
pDataReader = odbcConnection.executeStoreProcReader(sqlCommand, sqlParamList);
item.picture_list = new List<string>();
while (pDataReader.Read())
{
item.picture_list.Add(pDataReader.GetString(0));
}
pDataReader.Close();
itemList.Add(item);
Pls let me know if anyone needs more explaination
try this
public class YourObject
{
[XmlArray("picture_list")]
[XmlArrayItem("picture")]
public List<string> picture_list { get; set; }
}
Assuming you have access to the class where property "picture_list" is defined, you simply need to decorate the picture_list property with the XmlElement attribute like so:
EDIT: also assuming you are using the XmlSerializer. If not, please clarify the serializer you are using.
public class YourObject
{
[XmlElement("picture")]
public List<string> picture_list { get; set; }
}

Categories

Resources