MultiSpeak API: How to Put Database Values in an Array - c#

I am working on MultiSpeak API--I am not familiar with that. A function is as follows:
public meter[] GetMeterByAccountNumber(string accountNumber) {
meter myMeter = new meter();//IS this declaration right?
//some query work and next is sql data reader
int i = 0;
while (rdr.Read())
{
myMeter[i].deviceClass = rdr["deviceClass"].ToString();//error: Cannot apply indexing with [] to type 'meter'
i++;
}
return myMeter[]; //generates ERROR: Value expected.
}
I don't know what this return type of 'GetMeterByAccountNumber' is but it does expect a return of meter[] array.

GetMeterByAccountNumber is not the return type, it's the function name.
You could do somthing like this, however I would call it GetMetersByAccountNumber as it returns an array/IEnumerable
Also i'm not sure what deviceClass has to do with account number..
using System.Linq;
using System.Collections.Generic
public IEnumerable<meter> GetMetersByAccountNumber(string accountNumber) {
var items = new List<meter>();
//some query work and next is sql data reader
while (rdr.Read())
{
var deviceClass = rdr["deviceClass"].ToString();
var meter = new meter();
//Im guessing meter has some properties to set ?
meter.deviceClass = deviceClass;
items.Add(meter);
}
return items.AsReadOnly();
}

Here is what works for me, based on #Richard Friend's Answer. Thanks Richard!
public meter[] GetMetersByAccountNumber(string accountNumber)
{
meter[] final_return;
var items = new List<meter>();
while (rdr.Read())
{
var meter = new meter();
meter.deviceClass = rdr["deviceClass"].ToString();
items.Add(meter);
}
final_return = items.ToArray();
return final_return;
}

Related

c# Async and await for loop with database

I'm facing a little problem. I've made a function that imports customers from my website to my database to create invoices and so.. When this function starts, it calls another function to import only new clients. Now I want to make this last function an await to prevent that my software at home can search for the newly imported customers. This customer import is pretty easy, it just selects only the customers which are not imported through a loop. But I also made some security's in there in case something goes wrong. You know, most errors come from human input errors... But what is the best way to make this function an async so that the other function can await while it's importing new customers?
public async Task<bool> ImportClients(bool onlyNewCustomers)
{
System.Data.DataTable Table = new System.Data.DataTable();
System.Data.DataTable CustomerTable = new System.Data.DataTable();
System.Data.DataTable KlantTable = new System.Data.DataTable();
int PrestaCustomerID = 0; //original customer id from the prestashop
int CustomerID = 0; //Original customerID from software customer
int CustomerIdInserted = 0; //id from the inserted customer id in the software
int Wait = 0; //This var is used for the mysql to wait a few miliseconds between x updates
string Sql = "";
string Prefix = "";
DateTime Bday;
//Vars for logging
int CustomersImported = 0;
StringBuilder NewCustomerInfo = new StringBuilder();
StringBuilder NewCustomerAddress = new StringBuilder();
//Select everything whithin the customers table. After that we look if the customer is imported else we update the clients credentials.
Sql =
"SELECT c.id_customer, id_gender, c.firstname, c.lastname, c.email, c.birthday, c.newsletter, c.optin, c.website, " +
"c.active, c.date_add, c.date_upd, c.imported FROM ps_customer c " +
(onlyNewCustomers ? "WHERE imported = 0 " : "") + "ORDER BY c.id_customer DESC;";
Table = Functions.SelectWebQuery(Sql);
if (Table.Rows.Count > 0)
{
for (int i = 0; i < Table.Rows.Count; i++)
{
if (somethingGoesWrong)
{
return false;
}
}
return await Task.WhenAll<bool>(true);
}
}
And what i've tried to call this function
public async static void OrderImport()
{
Functions fns = new Functions();
bool importCustomers = await fns.ImportClients(true);
}
I'm using .net 4.5 with mysql database in winforms.
Thanks!
Paul
My advice would be not to return a Task<bool>, but to return the newly imported customers. If there are no new customers, or there are minor errors, that are probably solved the next time that you import new customers, return an empty list. For errorst that need immediate action raise an exception.
FurtherMore I'd make an extra method to fetch new customers: FetchNewCustomers is easier to understand what it does than FetchCustomers(true).
public Task<ICollection<Customer> FetchNewCustomersAsync()
{
return FetchCustomersAsync(true);
}
public Task<ICollection<Customer> FetchCustomersAsync(bool newOnly)
{
... // TODO: implement
}
Apparently you have a method Functions.SelectWebQuery(string) that returns DataTable. This returned DataTable needs to be converted to a sequence of Customers.
As an extension method. See extension methods demystified
public static IEnumerable<Customer> ToCustomers(this DataTable table)
{
// in this method you handle the problems if the table is not a table of Customers
foreach(DataRow dataRow in table.AsEnumerable)
{
Customer customer = new Customer()
{
... // fetch values from DataRow: dataRow.Field<string>("Name");
}
yield return customer;
}
}
Usage:
string sql = ...
IEnumerable<Customer> customers = Functions.SelectWebQuery(sql).ToCustomers()
Or the async version:
IEnumerable<Customer> customers = (await Functions.SelectWebQueryAsync(sql))
.ToCustomers();
You need to select a sql, depending on whether you want all Customers or only the new Customers:
public string sqlTextAllCustomers {get; }
public string sqlTextNewCustomers {get; }
Now we are ready to implement FetchCustomersAsync:
public Task<ICollection<Customer> FetchCustomersAsync(bool newOnly)
{
string sqlText = newOnly ? sqlTextNewCustomer : sqlTextAllCustomers;
try
{
// in baby steps:
DataTable fetchedData = await Functions.SelectWebQuery(sqlText);
return fetchedData.ToCustomers();
}
catch(Exception exc)
{
// TODO: detect if serious error or not
if (isSeriousError)
throw exc;
else
{
// not a serious error: we'll process the new customers next time
return Enumerable.Empty<Customer>();
}
}
}

Using ValueTuple returns Item1,Item2 why?

The next api returns in Postmen and to the client item1,item2
While I am using ValueTuple to change the names (the names not so important, but I can’t return item1,item2)
public async Task<(List<CategoryFilterResponseDTO> categoryFilters, string MetaDataDescription)> GetCategoryFilterPage([FromBody]categoryFilterRequestDTO categoryFilterRequest)
{
var logItem = new LogDTO();
var result = await _service.GetCategoryFilterPage(categoryFilterRequest);
try
{
OnStart(logItem, new object[] { categoryFilterRequest });
var categoryFilters = result.categoryFilters;
var MetaDataDescription = result.MetaDataDescription;
return (categoryFilters: categoryFilters, MetaDataDescription: MetaDataDescription);
}
}
the method:
public async Task<(List<CategoryFilterResponseDTO> categoryFilters, string MetaDataDescription)> GetCategoryFilterPage(categoryFilterRequestDTO categoryFilterRequestDTO)
{
List<CategoryFilterResponseDTO> categoryFilter = new List<CategoryFilterResponseDTO>();
List<FavoriteDTO> isFavorite = null;
string MetaDataDescription = "";
(List<FilterSortDTO<FlatSearchCategory>>, int) searchCategory = await _clubRepo.CategoryFilterPage(categoryFilterRequestDTO);//BranchesCount
if (searchCategory.Item2 == 0)
{
MetaDataDescription = GetCategoryDetails(categoryFilterRequestDTO.CategoryFirstFatherID.Value).CategoryName;
return (categoryFilters: categoryFilter, MetaDataDescription: MetaDataDescription);
}
You can change your return to the following:
return Ok(new
{
categoryFilters = categoryFilter,
metaDataDescription = MetaDataDescription
});
You will need to change your return type to ActionResult or similar as well.
Because that's the name of the fields on a ValueTuple<,>.
The names given to the values are only available to source code.

Get list/multiset from informix to C#

I'm making a library for connecting an Informix database with a C# extension for use in Outsystems.
So, now I've hit a wall. I need to receive a list/multiset from the db. How can I do that? I'm using the IfxDataReader to receive the data. But I see no method that could work.
Here is how we can send a list/multiset input parameter. But I need to receive it from a result set.
EDIT: Seeing as this was frowned upon by someone I'll provide some code and my try at it to see if you think it's correct (can't test it right now as I don't yet have data on the database... I'll test it in the end):
ssBensAndFotos = new RLBensAndFotos_BemRecordList();
DatabaseConnection dc = new DatabaseConnection(ssDatabase, ssHost, ssServer, ssService, ssProtocol, ssUserID, ssPassword);
try
{
dc.Conn = new IfxConnection(dc.ConnectionString);
dc.Cmd = new IfxCommand("get_bens_and_fotos_by_id_diligencia", dc.Conn);
dc.Cmd.CommandType = CommandType.StoredProcedure;
dc.Cmd.Parameters.Add(new IfxParameter("pi_id_diligencia", IfxType.Integer) { Direction = ParameterDirection.Input, Value = sspi_id_diligencia });
dc.Conn.Open();
using (IfxDataReader reader = dc.Cmd.ExecuteReader())
if (reader.HasRows)
while (reader.Read())
{
var bensAndFotos = new STBensAndFotos_BemStructure()
{
ssid_bem = reader.GetInt32(0),
ssnumero = reader.GetInt32(1),
ssespecie = reader.GetString(2),
ssbem = reader.GetString(3),
ssvalor = reader.GetDecimal(4),
sscomum = reader.GetInt32(5),
ssvoice_record = AuxiliaryMethods.CreateByteArrayFromIfxBlob(reader.GetIfxBlob(6))
};
// Here I get the string, split it and check to see which members of the array are integers, since in this case I'll be getting a multiset of int's
var multisetString = reader.GetString(7).Split('\'');
int n;
foreach (var item in multisetString)
if (int.TryParse(item, out n))
bensAndFotos.ssfotos.Add(new STBensAndFotos_FotoStructure() { ssfoto = n });
ssBensAndFotos.Add(bensAndFotos);
}
dc.Conn.Close();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
LIST, MULTISET and SET are mapped to String. You should be able to use IfxDataReader.GetString() to get the data.

MongoDB not querying

Hi I am trying to query my Mongo Database by using a list of Facebook ID's as the parameter in order to return the list of users with corresponding accounts. The method works fine in the Unity Editor however when I run it on iOS I get a constructor error (I have set a blank default constructor in order to solve the issue however it still doesn't work)
Initial Method
public void FetchData()
{
//data = Mongo.Instance.players.FindAll().ToList();
if (FB.IsLoggedIn)
{
FB.API("me/friends", HttpMethod.GET, FriendsHighscoreHndlr);
}
}
Callback Method
public void FriendsHighscoreHndlr (IGraphResult FBresult){
var dict = Json.Deserialize(FBresult.ToString()) as Dictionary<string,object>;
var friendList = new List<object>();
friendList = (List<object>)(dict["data"]);
int _friendCount = friendList.Count;
Debug.Log("Found friends on FB, _friendCount ... " +_friendCount);
List<string> friendIDsFromFB = new List<string>();
for (int i=0; i<_friendCount; i++) {
string friendFBID = getDataValueForKey( (Dictionary<string,object>)(friendList[i]), "id");
string friendName = getDataValueForKey( (Dictionary<string,object>)(friendList[i]), "name");
Debug.Log( i +"/" +_friendCount +" " +friendFBID +" " +friendName);
friendIDsFromFB.Add(friendFBID);
}
//friendIDsFromFB.Add(AccessToken.CurrentAccessToken.UserId);
var query = Query.In("facebookID", BsonArray.Create(friendIDsFromFB));
//Debug.Log(query);
data = Mongo.Instance.players.Find(query).ToList();
}
Data Value for Key Method
private string getDataValueForKey(Dictionary<string, object> dict, string key) {
object objectForKey;
if (dict.TryGetValue(key, out objectForKey)) {
return (string)objectForKey;
} else {
return "";
}
}
Return Query Result
{
"_id" : ObjectId("XXXXXX"),
"facebookID" : "XXXXXXXXXXXXXX",
"name" : "John Doe",
"highScore" : 40501
}
Have you tried using a filter from Mongo's .NET drivers?
I would suggest trying something like the example below. (Note: this event is being fired on a pre-defined object which is being defined as a collection.)
var filter = Builders<Object>.Filter.Eq(obj => obj.attribute, List<IDs>);

Updating an EntityFramework Record with relating new records

I am trying to use one attach to the EF to update all the records I need.
public void UpdateSale(Sale s)
{
Context.Sales.Attach(s);
Context.Entry(s).State = System.Data.Entity.EntityState.Modified;
Context.SaveChanges();
}
Lets Say like so. The above code gives me an error because it says the primary keys I am trying to add already exist(They arent automatically generated yet)
Now Sale has a number of different other Entity Models inside it like:
SavedForm, ProductSale
Now the code calling the UpdateSale is here
public JsonResult AddNewForms(string Anamaka, string NispahB, string Hazaot, string ManufactorerID, string ClientStatus, string TypeFile)
{
BL.FormConnectorLogic fcl = new BL.FormConnectorLogic();
DAL.SavedForm AnamakaForm = MakeSavedForm(Boolean.Parse(Anamaka),"מסמך הנמקה",ClientStatus);
DAL.SavedForm NispahBForm = MakeSavedForm(Boolean.Parse(NispahB), "נספח ב", ClientStatus);
DAL.SavedForm HazaotForm = MakeSavedForm(Boolean.Parse(Hazaot), TypeFile, ClientStatus, ManufactorerID);
var results = new { A = AnamakaForm, N = NispahBForm, H = HazaotForm };
return Json(results, JsonRequestBehavior.AllowGet);
}
public DAL.SavedForm MakeSavedForm(bool Authorized, string FormName, string ClientStatus, string ManufactorerID = "")
{
DAL.Sale s = (DAL.Sale)Session["SaleSave"];
DAL.SavedForm sf = new DAL.SavedForm();
if (Authorized)
{
sf = new DAL.SavedForm();
sf.FormName = new BL.FormConnectorLogic().getFormByName(FormName, ClientStatus, ManufactorerID).FormName;
sf.DateFormed = DateTime.Now;
sf.AgentID = s.AgentID;
sf.Status = "פתוח";
sf.SaleID = s.ID;
s.SavedForms.Add(sf);
new BL.SaleLogic().UpdateSale(s);
Session["SaleSave"] = s;
return sf;
}
else return null;
}
Now I've read up on the State and there is a difference between Added and Modified.
While I can't really seem to tell when I am going to add and when I am going to modify.
Is there anyway to disregard everything and to just shove my whole class and all its relationships to the database?

Categories

Resources