SQLite round midpoint - sqlite

I'm trying to use the SQLite function ROUND like this:
select ROUND(1.655, 2)
The result is 1.65, but i need this to round up to 1.66, like on c#
Math.Round(1.655, 2, MidpointRounding.AwayFromZero)
Is there a way to do this?

So i've been trying to use the Colonel Thirty Two tip, of using the Binding functions, but sqlite-net doesn't provide such functionality.
I've turn to the System.Data.SQLite.dll, so to help others:
First create a custom function in c#
[SQLiteFunction(Name = "RoundAccounting", Arguments = 2, FuncType = FunctionType.Scalar)]
public class RoundAccounting : SQLiteFunction
{
public override object Invoke(object[] args)
{
decimal value = 0;
int decimalPlaces = 0;
if(decimal.TryParse(args[0].ToString(), out value) && int.TryParse(args[1].ToString(), out decimalPlaces))
return Math.Round(value, decimalPlaces, MidpointRounding.AwayFromZero);
return 0;
}
}
then on the data layer we bind the function to the connection created:
using (SQLiteConnection connection = new SQLiteConnection(string.Format("Data Source={0}", dbPath)))
{
var function = new RoundAccounting();
var attributes = function.GetType().GetCustomAttributes(typeof(SQLiteFunctionAttribute), true).Cast<SQLiteFunctionAttribute>().ToArray();
await connection.OpenAsync();
connection.BindFunction(attributes[0], function);
SQLiteCommand command = new SQLiteCommand("SELECT RoundAccounting(somecolumn, 2);", connection); .....

Related

Creating RocksDB SST file in Java for bulk loading

I am new to RocksDB abd trying to create a SST file in Java for bulk loading. Eventual usecase is to create this in Apache Spark.
I am using rocksdbjni 6.3.6 in Ubuntu 18.04.03
I am keep getting this error,
org.rocksdb.RocksDBException: Keys must be added in order
at org.rocksdb.SstFileWriter.put(Native Method)
at org.rocksdb.SstFileWriter.put(SstFileWriter.java:104)
at CreateSSTFile.main(CreateSSTFile.java:34)
The sample code is
public static void main(String[] args) throws RocksDBException {
RocksDB.loadLibrary();
final Random random = new Random();
final EnvOptions envOptions = new EnvOptions();
final StringAppendOperator stringAppendOperator = new StringAppendOperator();
Options options1 = new Options();
SstFileWriter fw = null;
ComparatorOptions comparatorOptions = new ComparatorOptions();
try {
options1 = options1
.setCreateIfMissing(true)
.setEnv(Env.getDefault())
.setComparator(new BytewiseComparator(comparatorOptions));
fw = new SstFileWriter(envOptions, options1);
fw.open("/tmp/db/sst_upload_01");
for (int index = 0; index < 1000; index++) {
Slice keySlice = new Slice(("Key" + "_" + index).getBytes());
Slice valueSlice = new Slice(("Value_" + index + "_" + random.nextLong()).getBytes());
fw.put(keySlice, valueSlice);
}
fw.finish();
} catch (RocksDBException ex) {
ex.printStackTrace();
} finally {
stringAppendOperator.close();
envOptions.close();
options1.close();
if (fw != null) {
fw.close();
}
}
}
If the loop index is less than 10 the file is created successfully and I was able to ingest that into rocks db.
Thanks in advance.
I think I found the problem with the code.
The keys must be in order for the SST. The way I do the looping and using String lexicographical comparison for ordering, produces incorrect ordering. Like comparing "10" and "9" would break the order. Instead of that, if I sort all the keys before inserting into SST file it works.
Map<String, String> data = new HashMap<>();
for (int index = 0; index < 1000; index++) {
data.put("Key-" + random.nextLong(), "Value-" + random.nextDouble());
}
List<String> keys = new ArrayList<String>(data.keySet());
Collections.sort(keys);
for (String key : keys) {
Slice keySlice = new Slice(key);
Slice valueSlice = new Slice(data.get(key));
fw.put(keySlice, valueSlice);
}
When I tried with integer keys I found the issue.
The keys in sstfile should be in increasing order.
so you can start from index=10 it will work.
In fact ,you can create Comparator extends DirectComparator to avoid sorted.
class MyComparator extends DirectComparator {
public MyComparator(ComparatorOptions copt) {
super(copt);
}
#Override
public String name() {
return "MyComparator";
}
#Override
public int compare(DirectSlice a, DirectSlice b) {
// always true
return 1;
}
}
}
then set option
options1.setComparator(new MyComparator(comparatorOptions));

Npgsql passing an array of parameters

I am new in using Npgsql and I tried to make an helper in my asp.net project so that I can call it conveniently in my controllers method.
npgsqlqueryhelper
public DataSet ExecuteQueryWithParams(string commandText, params NpgsqlParameter[] parameters)
{
using (var connection = npgsqlcon.GetnpgsqlConnection())
using (NpgsqlCommand command = new NpgsqlCommand(commandText, connection))
{
DataSet ds = new DataSet();
command.Parameters.AddRange(parameters);
command.CommandTimeout = 5000;
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
da.Fill(ds);
connection.Close();
return ds;
}
}
My Controller Method
List<rollingPAR> rollingparlist = new List<rollingPAR>();
npgsqlhelper = new npgsqlQueryHelper();
NpgsqlParameter[] parameterList = {
new NpgsqlParameter("#lid", r.lid),
new NpgsqlParameter("#posting_date", r.date_end)
};
var table = npgsqlhelper.ExecuteQueryWithParams("SELECT ln.get_payment_status()", parameterList).Tables[0];
rollingparlist = table.AsEnumerable().Select(row => new rollingPAR
{
get_payment_status = row.Field<int>("get_payment_status")
}).ToList();
As I tried to run my program, I always encountered an error saying that function ln.get_payment_status() does not exist but when I tried to supply the parameters directly on the query
(e.g var table = npgsqlhelper.ExecuteQueryWithParams("SELECT ln.get_payment_status(1231,'06-18-2019')", parameterList).Tables[0];)
It gives me the data that I need. I don't know what is my mistake and I'm stuck here since yesterday. Can anyone help me with this? TIA
The parameter place holders are not automatically included in the function call. Try adding them:
var table = npgsqlhelper.ExecuteQueryWithParams("SELECT ln.get_payment_status(#lid,#posting_date)", parameterList).Tables[0];
With the help of Sir #JGH, it turns out that my query is missing the parameter placeholders but after I edit it, I encountered an error regarding the datatype between the asp.net datetime and postgresql date so I added this code to remove the error.
parameterList[1].NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Date;
So here is now the new code:
List<rollingPAR> rollingparlist = new List<rollingPAR>();
npgsqlhelper = new npgsqlQueryHelper();
NpgsqlParameter[] parameterList = {
new NpgsqlParameter("#lid", r.lid),
new NpgsqlParameter("#posting_date", r.date_end)
};
parameterList[1].NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Date;
var table = npgsqlhelper.ExecuteQueryWithParams("SELECT ln.get_payment_status(#lid,#posting_date)", parameterList).Tables[0];
rollingparlist = table.AsEnumerable().Select(row => new rollingPAR
{
get_payment_status = row.Field<int?>("get_payment_status")
}).ToList();
Thank you sir #JGH

ServiceStack OrmLite - Elegant way to handle SQL Server Connection Drops

We are currently using ORMLite and it is working really well.
One of the places that we are using it is for running large batch processes.
These processes run a single large batch all within a single transaction, if there are any errors then it rolls back the transaction and then it needs to be run again.
Is there a way that something like a connection drop(which could be very quick) could be better handled and that it could then, just re-establish the connection and then re-continue from there?
The only thing that's resembles something close to what you're after is using a Custom OrmLite Exec Fitler which you can use to inject your own custom Execution strategy.
The example on OrmLite's home page shows an example of using an Exec filter to execute each query 3 times:
public class ReplayOrmLiteExecFilter : OrmLiteExecFilter
{
public int ReplayTimes { get; set; }
public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
{
var holdProvider = OrmLiteConfig.DialectProvider;
var dbCmd = CreateCommand(dbConn);
try
{
var ret = default(T);
for (var i = 0; i < ReplayTimes; i++)
{
ret = filter(dbCmd);
}
return ret;
}
finally
{
DisposeCommand(dbCmd);
OrmLiteConfig.DialectProvider = holdProvider;
}
}
}
OrmLiteConfig.ExecFilter = new ReplayOrmLiteExecFilter { ReplayTimes = 3 };
using (var db = OpenDbConnection())
{
db.DropAndCreateTable<PocoTable>();
db.Insert(new PocoTable { Name = "Multiplicity" });
var rowsInserted = db.Count<PocoTable>(x => x.Name == "Multiplicity"); //3
}
But it uses the same IDbConnection, i.e. it doesn't create a new DB Connection.

How to pass non-optional NULL parameters to a Stored Proc using OrmLite

I'm using OrmLite against an existing SQL Server database that has published stored procedures for access. One of these SPs takes 3 int parameters, but expects that one or another will be null. However, none of the parameters are declared optional.
Here's the code I've tried:
using (IDbConnection scon = myFactory.OpenDbConnection())
{
rowCount = scon.SqlScalar<int>("EXEC myProc #FileID, #FileTypeID, #POID",
new
{
FileID = req.FileId,
FileTypeID = (int?)null,
POID = req.PoId,
});
}
But this produces a SqlException: Must declare the scalar variable "#FileTypeID". Examining the SQLParameterCollection under the covers shows that only two parameters are being generated by OrmLite.
Is it possible to call this SP with a null parameter?
It's not supported with SqlScalar. When you look at the code then you can see that SqlScalar methods from class ServiceStack.OrmLite.OrmLiteReadExtensions execute SetParameters method responsible for adding parameters to query with second parameter(excludeNulls) equal true I don't know why- mythz should answer for this ;).
If you want to fix it then you have change all SqlScalar methods to invoke SetParameters with true and SetParameters method should look like following(must support DBNull.Value not null)
private static void SetParameters(this IDbCommand dbCmd, object anonType, bool excludeNulls)
{
dbCmd.Parameters.Clear();
lastQueryType = null;
if (anonType == null) return;
var pis = anonType.GetType().GetSerializableProperties();
foreach (var pi in pis)
{
var mi = pi.GetGetMethod();
if (mi == null) continue;
var value = mi.Invoke(anonType, new object[0]);
if (excludeNulls && value == null) continue;
var p = dbCmd.CreateParameter();
p.ParameterName = pi.Name;
p.DbType = OrmLiteConfig.DialectProvider.GetColumnDbType(pi.PropertyType);
p.Direction = ParameterDirection.Input;
p.Value = value ?? DBNull.Value; // I HAVE CHANGED THAT LINE ONLY
dbCmd.Parameters.Add(p);
}
}
When you change code then you can set null for parameters in the following way:
var result = db.SqlScalar<int>("EXEC DummyScalar #Times", new { Times = (int?)null });
In my opinion you can describe it as a defect on github and I can make pull request.

How to dynamically set a property of a class without using reflection (with dynamic) in C# 4 when property name is coming from another source

I'm building/updating an EntityFramework EntityObject on runtime. I want to set the properties of the entity class, property names and values are coming from another source.
So I'm doing this;
public static EntityCollection<T> UpdateLocaleEntity<T>(EntityCollection<T> entityCollectionToUpdate, params ILocaleControl[] values) where T : EntityObject
{
foreach (var x in entityCollectionToUpdate)
{
Type t = typeof(T);
dynamic localeEntity = x;
string cultureCode = localeEntity.CultureCode;
for (int j = 0; j < values.Length; j++)
{
var value = values[j].GetLocaleValue(cultureCode);
t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);
}
}
return entityCollectionToUpdate;
}
So, how can I get rid of "t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);" part, is there a dynamic way of doing this?
Something like;
dynamicCastedLocaleEntity.GetProperty(values[j].EntityPropertyName) = value;
Thanks.
Long answer coming up.
Reflection is great in many situations, horrible in some but in almost all cases it's slow.
There are at least 4 different ways to set a property in .NET without having to use reflection.
I thought I demonstrate one of them: Using compiled expression trees. Note that the expression building is rather expensive too so that's why it's very important to cache the delegate one builds with it in a dictionary (for instance):
Expression Trees was introduced in .NET35 and is used for many things. Here I use them to build a property setter expression and then compile it into a delegate.
The example demonstrates different timing for the different cases but here are my numbers:
Control case (hard coded): 0.02s
Reflection: 1.78s
Expression Tree: 0.06s
using System;
using System.Linq.Expressions;
namespace DifferentPropertSetterStrategies
{
class TestClass
{
public string XY
{
get;
set;
}
}
class DelegateFactory
{
public static Action<object, object> GenerateSetPropertyActionForControl(
)
{
return (inst, val) => ((TestClass) inst).XY = (string) val;
}
public static Action<object, object> GenerateSetPropertyActionWithReflection(
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
return (inst, val) => propertyInfo.SetValue (inst, val, null);
}
public static Action<object,object> GenerateSetPropertyActionWithLinqExpression (
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
var propertyType = propertyInfo.PropertyType;
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var valueParameter = Expression.Parameter(typeof(object), "value");
var lambda = Expression.Lambda<Action<object, object>> (
Expression.Assign (
Expression.Property (Expression.Convert (instanceParameter, type), propertyInfo),
Expression.Convert(valueParameter, propertyType)),
instanceParameter,
valueParameter
);
return lambda.Compile();
}
}
static class Program
{
static void Time (
string tag,
object instance,
object value,
Action<object, object > action
)
{
// Cold run
action(instance, value);
var then = DateTime.Now;
const int Count = 2000000;
for (var iter = 0; iter < Count; ++iter)
{
action (instance, value);
}
var diff = DateTime.Now - then;
Console.WriteLine ("{0} {1} times - {2:0.00}s", tag, Count, diff.TotalSeconds);
}
static void Main(string[] args)
{
var instance = new TestClass ();
var instanceType = instance.GetType ();
const string TestProperty = "XY";
const string TestValue = "Test";
// Control case which just uses a hard coded delegate
Time(
"Control",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionForControl ()
);
Time(
"Reflection",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithReflection (instanceType, TestProperty)
);
Time(
"Expression Trees",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithLinqExpression(instanceType, TestProperty)
);
Console.ReadKey();
}
}
}
For FuleSnabel's answer, you can speed it up a lot (sometimes twice as fast in my tests). In some tests, it was just as fast as the Control solution:
public static Action<Object,Object> GenerateSetPropertyActionWithLinqExpression2(Type type, String property) {
PropertyInfo pi = type.GetProperty(property,BindingFlags.Instance|BindingFlags.Public);
MethodInfo mi = pi.GetSetMethod();
Type propertyType = pi.PropertyType;
var instance = Expression.Parameter(typeof(Object), "instance");
var value = Expression.Parameter(typeof(Object), "value");
var instance2 = Expression.Convert(instance, type);
var value2 = Expression.Convert(value, pi.PropertyType);
var callExpr = Expression.Call(instance2, mi, value2);
return Expression.Lambda<Action<Object,Object>>(callExpr, instance, value).Compile();
}
possibly not with EntityObject, but if you've had an ExpandoObject than you can do
dynamic entity = new ExpandoObject();
(entity as IDictionary<String, Object>)[values[j].EntityPropertyName] = value
The open source framework ImpromptuInterface has methods to invoke based on a string using the DLR rather than reflection and runs faster than reflection too.
Impromptu.InvokeSet(localeEntity, values[j].EntityPropertyName,value);
I'm afraid not. Any use of a dynamic object is baked-in at compile time. Any call which could vary at run-time has to be done using reflection.

Resources