How to make a 'raw' query for WP8 sqlite-net - c#

I am doing WP8 with sqlite-net. Sometime I wish to make a raw query without defining Table Model everytime.
What I did is is make a query below, and try to get its property:
string query = "SELECT firstname, lastname FROM users";
var records = db.Query<object>(query).ToList();
foreach (var r in records)
{
System.Diagnostics.Debug.WriteLine(r.GetType().GetProperty("firstname").GetValue(r,null).toString());
}
However, an Exception of "System.NullReferenceException" happens.
May I know how do I actually get the value without declaring Table Model?

Simply:
string query = "SELECT firstname, lastname FROM users";
Statement stQuery = SQLite3.Prepare2(connection.Handle, query);
while ((SQLite3.Result result = SQLite3.Step(stQuery)) == SQLite3.Result.Row)
{
//your stuff here
}
SQLite3.Finalize(stQuery);

you can extend the partial class in this way:
namespace SQLite
{
public partial class SQLiteConnection
{
public List<object[]> CustomQuery(string query, params object[] args)
{
var cmd = CreateCommand(query, args);
return cmd.ExecuteCustomQuery();
}
}
public partial class SQLiteCommand
{
public List<object[]> ExecuteCustomQuery()
{
if (SQLiteConnection.Trace)
{
Debug.WriteLine("Executing Query: " + this);
}
var stmt = Prepare();
try
{
var colLenght = SQLite3.ColumnCount(stmt);
var lstRes = new List<object[]>();
while (SQLite3.Step(stmt) == SQLite3.Result.Row)
{
var obj = new object[colLenght];
lstRes.Add(obj);
for (int i = 0; i < colLenght; i++)
{
var colType = SQLite3.ColumnType(stmt, i);
switch (colType)
{
case SQLite3.ColType.Blob:
obj[i] = SQLite3.ColumnBlob(stmt, i);
break;
case SQLite3.ColType.Float:
obj[i] = SQLite3.ColumnDouble(stmt, i);
break;
case SQLite3.ColType.Integer:
obj[i] = SQLite3.ColumnInt(stmt, i);
break;
case SQLite3.ColType.Null:
obj[i] = null;
break;
case SQLite3.ColType.Text:
obj[i] = SQLite3.ColumnString(stmt, i);
break;
}
}
}
return lstRes;
}
finally
{
SQLite3.Finalize(stmt);
}
}
}
}
and after you have a method that return a list of array of object that you can call in this way:
var query = "select c.Id, c.Name, (select count(*) from Products where IdCategory = c.Id) from Categories c order by c.Name";
var lst = this.SqlConn.CustomQuery(query);
return (from s in lst
select new CategoryDescriptor {
Id = (int) s[0],
Name = (string) s[1],
ProductsCount = (int) s[2]
});

Using the top two answers (first answer required changing the source code, and second was incomplete)
I came up with this method:
public List<object[]> RunSql(string sqlString, bool includeColumnNamesAsFirstRow)
{
var lstRes = new List<object[]>();
SQLitePCL.sqlite3_stmt stQuery = null;
try
{
stQuery = SQLite3.Prepare2(fieldStrikeDatabase.Connection.Handle, sqlString);
var colLenght = SQLite3.ColumnCount(stQuery);
if (includeColumnNamesAsFirstRow)
{
var obj = new object[colLenght];
lstRes.Add(obj);
for (int i = 0; i < colLenght; i++)
{
obj[i] = SQLite3.ColumnName(stQuery, i);
}
}
while (SQLite3.Step(stQuery) == SQLite3.Result.Row)
{
var obj = new object[colLenght];
lstRes.Add(obj);
for (int i = 0; i < colLenght; i++)
{
var colType = SQLite3.ColumnType(stQuery, i);
switch (colType)
{
case SQLite3.ColType.Blob:
obj[i] = SQLite3.ColumnBlob(stQuery, i);
break;
case SQLite3.ColType.Float:
obj[i] = SQLite3.ColumnDouble(stQuery, i);
break;
case SQLite3.ColType.Integer:
obj[i] = SQLite3.ColumnInt(stQuery, i);
break;
case SQLite3.ColType.Null:
obj[i] = null;
break;
case SQLite3.ColType.Text:
obj[i] = SQLite3.ColumnString(stQuery, i);
break;
}
}
}
return lstRes;
}
catch (Exception)
{
return null;
}
finally
{
if (stQuery != null)
{
SQLite3.Finalize(stQuery);
}
}
}

Related

ASP.NET - Help to understand this block of code

I'm trying to understand a block of code from a school project, but I'm not understanding what this does.
I know that this is a controller method and is passing some information to the view?
Can you help me?
public ActionResult Index(int ? page, string sort) {
using(istecEntities ctx = new istecEntities()) {
var Persons = ctx.Persons.ToList()
.Select(p => new Person {
Num = p.num,
Name = p.Name,
Area = p.Area,
Grades = p.Grades as List <Grade>
}).ToList<Person>();
switch (sort) {
case "numdesc":
Persons = Persons.OrderByDescending(p =>p.Num).ToList<Person>();
break;
case "NameDesc":
Persons = Persons.OrderByDescending(p =>p.Name).ToList<Person>();
break;
case "NameAsc":
Persons = Persons.OrderBy(p =>p.Name).ToList<Person>();
break;
default:
Persons = Persons.OrderBy(p =>p.Num).ToList<Person>();
break;
}
ViewBag.sortnum = (String.IsNullOrEmpty(sort)) ?
"numdesc": "";
ViewBag.sortName = (sort == "NameDesc") ?
"NameAsc": "NameDesc";
ViewBag.sort = sort;
int size = 3;
int pagenumber = (page ?? 1);
return View(Persons.ToPagedList<Person>(pagenumber, size));
}
}

Google Reporting API V4 Missing Values

I've been having a problem with Google's analytic reporting api v4. When I make a request, i can get data back, but some dimension and metric values are missing and/or inconsistent.
For example if i wanted the fullRefferer, it would return (not set). Or when i do get values my page views value could be 1312 and my sessions could be 26.
My code for making the request is below:
public GetReportsResponse Get(string viewId, DateTime startDate, DateTime endDate, string nextPageToken = null)
{
try
{
var credential = GetCredential();
using (var svc = new AnalyticsReportingService(
new BaseClientService.Initializer
{
HttpClientInitializer = credential
}))
{
var mets = new List<Metric>
{
new Metric
{
Alias = "Users",
Expression = "ga:users"
},
new Metric
{
Alias = "Bounce Rate",
Expression = "ga:bounceRate"
},
new Metric
{
Alias = "Page Views",
Expression = "ga:pageViews"
},
new Metric()
{
Alias = "Sessions",
Expression = "ga:sessions"
}
};
var dims = new List<Dimension>
{
new Dimension { Name = "ga:date" },
new Dimension { Name = "ga:hour" },
new Dimension { Name = "ga:browser" },
new Dimension { Name = "ga:pagePath" },
new Dimension { Name = "ga:fullReferrer"}
};
var dateRange = new DateRange
{
StartDate = startDate.ToFormattedString(),
EndDate = endDate.ToFormattedString()
};
var reportRequest = new ReportRequest
{
DateRanges = new List<DateRange> { dateRange },
Dimensions = dims,
Metrics = mets,
ViewId = viewId,
PageToken = nextPageToken
};
var getReportsRequest = new GetReportsRequest
{
ReportRequests = new List<ReportRequest> { reportRequest },
};
var batchRequest = svc.Reports.BatchGet(getReportsRequest);
var response = batchRequest.Execute();
return response;
}
}
catch (Exception e)
{
return null;
}
}
And my code for filtering the results is here:
public static List<AnalyticEntry> Filter(Google.Apis.AnalyticsReporting.v4.Data.GetReportsResponse response)
{
if (response == null) return new List<AnalyticEntry>();
List<GoogleDataDto> gData = new List<GoogleDataDto>();
foreach (var report in response.Reports)
{
foreach (var row in report.Data.Rows)
{
GoogleDataDto dto = new GoogleDataDto();
foreach (var metric in row.Metrics)
{
foreach (var value in metric.Values)
{
int index = metric.Values.IndexOf(value);
var metricHeader = report.ColumnHeader.MetricHeader.MetricHeaderEntries[index];
switch (metricHeader.Name)
{
case "Sessions":
dto.Sessions = Convert.ToInt32(value);
break;
case "Bounce Rate":
dto.BounceRate = Convert.ToDecimal(value);
break;
case "Page Views":
dto.PageViews = Convert.ToInt32(value);
break;
case "Users":
dto.Users = Convert.ToInt32(value);
break;
}
}
}
foreach (var dimension in row.Dimensions)
{
int index = row.Dimensions.IndexOf(dimension);
var dimensionName = report.ColumnHeader.Dimensions[index];
switch (dimensionName)
{
case "ga:date":
dto.Date = dimension;
break;
case "ga:hour":
dto.Hour = dimension;
break;
case "ga:browser":
dto.Browser = dimension;
break;
case "ga:pagePath":
dto.PagePath = dimension;
break;
case "ga:source":
dto.Source = dimension;
break;
case "ga:fullRefferer":
dto.Referrer = dimension;
break;
}
}
gData.Add(dto);
}
}
return Combine(gData);
}
private static List<AnalyticEntry> Combine(IReadOnlyCollection<GoogleDataDto> gData)
{
List<AnalyticEntry> outputDtos = new List<AnalyticEntry>();
var dates = gData.GroupBy(d => d.Date.Substring(0,6)).Select(d => d.First()).Select(d => d.Date.Substring(0,6)).ToList();
foreach (var date in dates)
{
var entities = gData.Where(d => d.Date.Contains(date)).ToList();
AnalyticEntry dto = new AnalyticEntry
{
Date = date.ToDate(),
PageViews = 0,
Sessions = 0,
Users = 0,
BounceRate = 0
};
foreach (var entity in entities)
{
dto.BounceRate += entity.BounceRate;
dto.PageViews += entity.PageViews;
dto.Users += entity.Users;
dto.Sessions += entity.Sessions;
}
dto.BounceRate = dto.BounceRate / entities.Count();
var dictionaries = entities.GetDictionaries();
var commonBrowsers = dictionaries[0].GetMostCommon();
var commonTimes = dictionaries[1].GetMostCommon();
var commonPages = dictionaries[2].GetMostCommon();
var commonSources = dictionaries[3].GetMostCommon();
var commonReferrers = dictionaries[4].GetMostCommon();
dto.CommonBrowser = commonBrowsers.Key;
dto.CommonBrowserViews = commonBrowsers.Value;
dto.CommonTimeOfDay = commonTimes.Key.ToInt();
dto.CommonTimeOfDayViews = commonTimes.Value;
dto.CommonPage = commonPages.Key;
dto.CommonPageViews = commonPages.Value;
dto.CommonSource = commonSources.Key;
dto.CommonSourceViews = commonSources.Value;
dto.CommonReferrer = commonReferrers.Key;
dto.CommonReferrerViews = commonReferrers.Value;
outputDtos.Add(dto);
}
return outputDtos;
}
I'm not sure what else to put, please comment for more info :)
Solved!
Originally I was trying to find a 'metric name' based on the location of a value in an array. So using the location I would get the name and set the value.
The problem was the array could have multiple values which were the same.
For example:
var arr = [1,0,3,1,1];
If a value was 1, I was trying to use the location of 1 in the array to get a name.
So if the index of 1 in the array was 0, I would find its name by using that index and finding the name in another array.
For example:
var names = ['a','b','c'];
var values = [1,2,1];
var value = 1;
var index = values.indexOf(value); // which would be 0
SetProperty(
propertyName:names[index], // being a
value: value);
Although its hard to explain I was setting the same value multiple times due to the fact that there were more than one value equal to the same thing in the array.
Here is the answer. Tested and works
public List<GoogleDataDto> Filter(GetReportsResponse response)
{
if (response == null) return null;
List<GoogleDataDto> gData = new List<GoogleDataDto>();
foreach (var report in response.Reports)
{
foreach (var row in report.Data.Rows)
{
GoogleDataDto dto = new GoogleDataDto();
foreach (var metric in row.Metrics)
{
int index = 0; // Index counter, used to get the metric name
foreach (var value in metric.Values)
{
var metricHeader = report.ColumnHeader.MetricHeader.MetricHeaderEntries[index];
//Sets property value based on the metric name
dto.SetMetricValue(metricHeader.Name, value);
index++;
}
}
int dIndex = 0; // Used to get dimension name
foreach (var dimension in row.Dimensions)
{
var dimensionName = report.ColumnHeader.Dimensions[dIndex];
//Sets property value based on dimension name
dto.SetDimensionValue(dimensionName, dimension);
dIndex++;
}
// Will only add the dto to the list if its not a duplicate
if (!gData.IsDuplicate(dto))
gData.Add(dto);
}
}
return gData;
}

Filter products with ElasticSearch concat a lot of filter

I've been trying to filter products with Elasticsearch for a few hours, unfortunately to no avail.
I need to find products that belong to certain categories and at the same time have selected several brands and one size.
Help :(
json screen
querycontainer build method
private QueryContainer CreateOrQueryFromFilter(QueryContainer queryContainer, SortedSet<string> filter, string fieldName)
{
if (filter != null && filter.Count > 0)
{
foreach (var item in filter)
{
queryContainer |= new TermQuery()
{
Name = fieldName + "named_query",
Boost = 1.1,
Field = fieldName,
Value = item
};
}
}
return queryContainer;
}
and search method
public ResultModel SearchRequest(RequestModel r)
{
string key = string.Format("search-{0}-{1}", r.CacheKey + "-" + ProductCatalog.Model.Extension.StringHelper.UrlFriendly(r.SearchText), r.Prefix);
node = new Uri("http://xxxx:9200/");
settings = new ConnectionSettings(node);
settings.DisableDirectStreaming();
settings.DefaultIndex("products");
client = new ElasticClient(settings);
// return AppCache.Get(key, () =>
// {
DateTime start = DateTime.Now;
ResultModel result = new ResultModel(r.Canonical, r.RouteObject);
if (!string.IsNullOrEmpty(r.Prefix))
{
result.Prefix = r.Prefix;
}
QueryContainer c = new QueryContainer();
if (r.CategoryFilterChilds != null && r.CategoryFilterChilds.Count > 0)
{
var a1 = new SortedSet<string>(r.CategoryFilterChilds.Select(a => (string)a.ToString()));
c = CreateOrQueryFromFilter(c, a1, "categories");
}
else
{
if (r.CategoryFilterRoots != null && r.CategoryFilterRoots.Count > 0)
{
var a1 = new SortedSet<string>(r.CategoryFilterRoots.Select(a => (string)a.ToString()));
c = CreateOrQueryFromFilter(c, a1, "categories");
}
else
{
// null
}
}
var filters = new AggregationDictionary();
if (r.IsBrandFilter)
{
c = CreateOrQueryFromFilter(c, r.SelectedBrands, "brands");
}
if (r.IsColorFilter)
{
c = CreateOrQueryFromFilter(c, r.SelectedBrands, "colors");
}
int skip = (r.Page * r.PageSize) - r.PageSize;
ISearchRequest r2 = new SearchRequest("products");
r2.From = 1;
r2.Size = r.PageSize;
r2.Query = c;
string[] Fields = new[] { "brands", "shopId" };
AggregationBase aggregations = null;
foreach (string sField in Fields)
{
var termsAggregation = new TermsAggregation("agg_" + sField)
{
Field = sField,
Size = 120,
Order = new List<TermsOrder> { TermsOrder.TermDescending }
};
if (aggregations == null)
{
aggregations = termsAggregation;
}
else
{
aggregations &= termsAggregation;
}
}
r2.Aggregations = aggregations;
var c2 = client.Search<ShopProductElastic>(r2);
var ShopsBuf = (Nest.BucketAggregate)(c2.Aggregations["agg_brands"]);
var ShopsCount = ShopsBuf.Items.Count();
var results = c2;
result.BrandsRequest = new SortedDictionary<string, int>();
foreach (Nest.KeyedBucket<object> item in ShopsBuf.Items)
{
result.BrandsRequest.Add((string)item.Key, (int)(item.DocCount ?? 0));
}
result.CategorySelected = r.CategoryCurrent;
result.TotalCount = 10;
var costam = results.Documents.ToList();
var targetInstance = Mapper.Map<List<Products>>(costam);
result.Products = targetInstance;
result.Page = r.Page;
result.PageSize = r.PageSize;
result.IsBrandFilter = r.IsBrandFilter;
result.IsColorFilter = r.IsColorFilter;
result.IsPatternFilter = r.IsPatternFilter;
result.IsSeasonFilter = r.IsSeasonFilter;
result.IsShopFilter = r.IsShopFilter;
result.IsSizeFilter = r.IsSizeFilter;
result.IsStyleFilter = r.IsStyleFilter;
result.IsTextileFilter = r.IsTextileFilter;
DateTime stop = DateTime.Now;
result.SearchTime = stop - start;
result.SearchText = r.SearchText;
return result;
// }, TimeSpan.FromHours(8));
}
I have all products that have a given brand or categories. However, i need all products of a selected brand in selected categories

Swiftly search for multiple partial strings in a huge string

I need to check whether all parts of a string like
A=1&AW=43&KO=96&R=7&WW=15&ZJ=80
are in a big string like:
A=1&AG=77&AW=43&.....&KF=11&KO=96&.....&QW=55&R=7&....&WV=1&WW=15&....ZJ=80&
My code splits the first string on & and uses Contains. But the duration is too long, as the big string is up to 800000 characters.
Is there a better/faster method for this?
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 EquipmentCompare(SqlString equip, SqlString comp)
{
SqlInt32 result = 1;
if (comp.IsNull)
{
result = 1;
}
else
{
string equipment = "&" + equip.ToString();
string compString = comp.ToString() + "! ";
while (compString.Length > 1)
{
string sub = compString.Substring(0, compString.IndexOf("!"));
compString = compString.Substring(compString.IndexOf("!")+1);
string[] elements = sub.Split('&');
foreach (string i in elements)
{
if (i.StartsWith("~"))
{
if (equipment.Contains("&" + i.Substring(1) + "&"))
{
result = 0;
break;
}
}
else if (!equipment.Contains("&" + i + "&"))
{
result = 0;
break;
}
else
{
result = 1;
continue;
}
}
if (result == 1)
{
break;
}
}
}
return result;
}
}
I think you may speed up your code by using HashSet. Try this:
var str1 = "A=1&AW=43&KO=96&R=7&WW=15&ZJ=80";
var str2 = "A=1&AG=77&AW=43&.....&KF=11&KO=96&.....&QW=55&R=7&....&WV=1&WW=15&....ZJ=80&";
var largeStringSet = new HashSet<string>(str2.Split('&'));
var allPartsIncluded = str1.Split('&').All(s => largeStringSet.Contains(s));

Generate IL to decrease counter in for loop

I am hacking around with the Good For Nothing (GFN) compiler, trying to make it do a few different things. I am using the code from here: https://github.com/johandanforth/good-for-nothing-compiler
Regular GFN for loop:
var x = 0;
for x = 0 to 3 do
print x;
end;
This for loop always increments. I'd like to add decrement functionality:
var x = 0;
for x = 3 to 0 down //up for increment (works same as do)
print x;
end;
The main area I am struggling with is the CodeGen.
ForLoop class:
public class ForLoop : Stmt
{
public Stmt Body { get; set; }
public Expr From { get; set; }
public string Ident { get; set; }
public Expr To { get; set; }
public ArithOp Type { get; set; }
}
ArithOp enum:
public enum ArithOp
{
Add,
Sub,
Mul,
Div,
Up,
Down
}
Inside CodeGen.cs:
private void GenStmt(Stmt stmt)
{
//code omitted for brevity
else if (stmt is ForLoop)
{
// example:
// for x = 0 to 100 up
// "hello";
// end;
// x = 0
var forLoop = (ForLoop)stmt;
var assign = new Assign { Ident = forLoop.Ident, Expr = forLoop.From };
GenStmt(assign);
// jump to the test
var test = _il.DefineLabel();
_il.Emit(OpCodes.Br, test);
// statements in the body of the for loop
var body = _il.DefineLabel();
_il.MarkLabel(body);
GenStmt(forLoop.Body);
// to (increment/decrement the value of x)
_il.Emit(OpCodes.Ldloc, SymbolTable[forLoop.Ident]);
_il.Emit(OpCodes.Ldc_I4, 1);
_il.Emit(forLoop.Type == ArithOp.Up ? OpCodes.Add : OpCodes.Sub);
GenerateStoreFromStack(forLoop.Ident, typeof(int));
// **test** does x equal 100? (do the test)
_il.MarkLabel(test);
_il.Emit(OpCodes.Ldloc, SymbolTable[forLoop.Ident]);
GenerateLoadToStackForExpr(forLoop.To, typeof(int));
_il.Emit(OpCodes.Blt, body);
}
}
private void GenerateStoreFromStack(string name, Type type)
{
if (!SymbolTable.ContainsKey(name))
throw new Exception("undeclared variable '" + name + "'");
var locb = SymbolTable[name];
var localType = locb.LocalType;
if (localType != type)
throw new Exception(string.Format("'{0}' is of type {1} but attempted to store value of type {2}", name,
localType == null ? "<unknown>" : localType.Name, type.Name));
_il.Emit(OpCodes.Stloc, SymbolTable[name]);
}
private void GenerateLoadToStackForExpr(Expr expr, Type expectedType)
{
Type deliveredType;
if (expr is StringLiteral)
{
deliveredType = typeof(string);
_il.Emit(OpCodes.Ldstr, ((StringLiteral)expr).Value);
}
else if (expr is IntLiteral)
{
deliveredType = typeof(int);
_il.Emit(OpCodes.Ldc_I4, ((IntLiteral)expr).Value);
}
else if (expr is Variable)
{
var ident = ((Variable)expr).Ident;
deliveredType = expr.GetType();
if (!SymbolTable.ContainsKey(ident))
{
throw new Exception("undeclared variable '" + ident + "'");
}
_il.Emit(OpCodes.Ldloc, SymbolTable[ident]);
}
else if (expr is ArithExpr)
{
var arithExpr = (ArithExpr)expr;
var left = arithExpr.Left;
var right = arithExpr.Right;
deliveredType = expr.GetType();
GenerateLoadToStackForExpr(left, expectedType);
GenerateLoadToStackForExpr(right, expectedType);
switch (arithExpr.Op)
{
case ArithOp.Add:
_il.Emit(OpCodes.Add);
break;
case ArithOp.Sub:
_il.Emit(OpCodes.Sub);
break;
case ArithOp.Mul:
_il.Emit(OpCodes.Mul);
break;
case ArithOp.Div:
_il.Emit(OpCodes.Div);
break;
default:
throw new NotImplementedException("Don't know how to generate il load code for " + arithExpr.Op +
" yet!");
}
}
else
{
throw new Exception("don't know how to generate " + expr.GetType().Name);
}
if (deliveredType == expectedType) return;
if (deliveredType != typeof (int) || expectedType != typeof (string))
throw new Exception("can't coerce a " + deliveredType.Name + " to a " + expectedType.Name);
_il.Emit(OpCodes.Box, typeof (int));
_il.Emit(OpCodes.Callvirt, typeof (object).GetMethod("ToString"));
}
This currently generates an .exe that does nothing. Sources I have looked at to help solve this: http://www.codeproject.com/Articles/3778/Introduction-to-IL-Assembly-Language#Loop and https://ninjaferret.wordpress.com/2009/12/23/msil-4-for-loops/. I just don't know enough IL
Do this in C# code to get insight:
for (int ix = 0; ix < 3; ++ix) // up
for (int ix = 3; ix > 0; --ix) // down
There are two changes, you got the difference in the inc/dec operator. You didn't get the change in the loop termination condition. Which makes this the bug:
_il.Emit(OpCodes.Blt, body);
You'll have to invert that to Opcodes.Bgt

Categories