Generate lambda expression from string - c#

I have a need to store lambda expressions in a database and execute them dynamically. The following snippet works well as is,
float result = dataRowArray.AsEnumerable().Sum(r => r.Field<float>("ColumnA") * r.Field<float>("ColumnB"));
but I'd like to store the following part in a string...
r => r.Field<float>("ColumnA") * r.Field<float>("ColumnB")
... and inject it dynamically as in:
float result = MySession.Current.dr.AsEnumerable().Sum(storedLambdaString);
I've done a ton of Googling but I'm coming up short. Any suggestions?

I suggest store the query in the database and execute using LINQ like below.
using (eEntities db = new eEntities())
{
string query = "select name,age,salary from employees"
var employees = db.Database.SqlQuery<Employee>(query).
}
Please note: Employee is here my custom class having properties same as queried.

Theres a nuget package that may help you "System.Linq.Dynamic". This sample code works...
public class TestRow
{
public Dictionary<string,float> Field { get; set; }
public TestRow()
{
this.Field = new Dictionary<string, float>();
this.Field.Add("ColumnA", 2);
this.Field.Add("ColumnB", 3);
}
}
class Program
{
static void Main(string[] args)
{
var testRow = new TestRow();
string expressionString = "r.Field[\"ColumnA\"] * r.Field[\"ColumnB\"]";
var parameter = Expression.Parameter(typeof(TestRow),"r");
var lambdaET = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { parameter }, typeof(float), expressionString);
var result = lambdaET.Compile().DynamicInvoke(testRow);
Console.WriteLine(result);
Console.ReadLine();
}
}

Related

Xamarin Forms delete from sqlite database

I have a class Announcement, and I have a list of id, I am using the nuget package: sqlite-net-pcl.
How can I delete an announcement from my Announcement table if I have it id. I am trynig to use linq like: await connection.DeleteAsync(announcement).Where(...)
but I can't use Where with the DeleteAsync, so I tried
var query = connection.Table<Announcement>().Where(announcement=>announcement.AnnouncementId == announcementId)
it gives me this erro :System.NotSupportedException: Cannot delete AsyncTableQuery`1: it has no PK
I think you are looking for something like this:
public static int Delete(string url)
{
using (var databaseManager = DatabaseManager.Instance)
{
lock (databaseManager)
{
return databaseManager.Database.Table<File>().Delete(x => x.Url == url);
}
}
}
This is using SQLite;
https://developer.xamarin.com/guides/android/data-and-cloud-services/data-access/part-3-using-sqlite-orm/
I have never used the nuget in question but I have had a quick look on the source and it would appear that TableQuery has a sync method called Delete that returns an integer.
The code you have included above is returning an object of type TableQuery<Announcement>. The class TableQuery contains the following definition:
public int Delete(Expression<Func<T, bool>> predExpr)
{
if (predExpr.NodeType == ExpressionType.Lambda) {
var lambda = (LambdaExpression)predExpr;
var pred = lambda.Body;
var args = new List<object> ();
var w = CompileExpr (pred, args);
var cmdText = "delete from \"" + Table.TableName + "\"";
cmdText += " where " + w.CommandText;
var command = Connection.CreateCommand (cmdText, args.ToArray ());
int result = command.ExecuteNonQuery();
return result;
} else {
throw new NotSupportedException ("Must be a predicate");
}
}
It would seem that you should just use the following:
connection.Table<Announcement>().Delete(announcement=>announcement.AnnouncementId == announcementId)
This code is completely untested and is from reviewing the source code of the nuget package on Github (https://github.com/praeclarum/sqlite-net/blob/master/src/SQLite.cs).
Have your ID Property the Primary Key Attribute ?
[PrimaryKey,AutoIncrement]
public int Id { get; set; }

ElasticSearch NEST Delete all document

I am using ElastciSearch 2.3.0
I am trying to delete documents from the ElasticSearch using .net and NEST for specific index.
I only want to delete all documents and not the _mapping
DeleteByQueryRequest r = new DeleteByQueryRequest(new IndexName() { Name = indexName });
r.QueryOnQueryString = "*";
var response = client.DeleteByQuery(r);
I am try to do this by using above code but it is not working.
Please suggest on what's wrong with the above code or how this can be done.
Thanks for your help in advance.
Don't use delete by query it was made a plugin since elastic 2.0 for a good reason. You can get out of memory exceptions easy.
You should delete the whole index and recreate the mappings
static void Main(string[] args)
{
ElasticClient db = new ElasticClient(new Uri("http://localhost.fiddler:9200"));
db.IndexMany(Enumerable.Range(0, 100).Select(i => new Data { Id = i, Name = "Name" + i }), "test_index");
var mappings = db.GetMapping<Data>();
var delete = db.DeleteIndex(new DeleteIndexRequest("test_index"));
var indexMapping = mappings.IndexTypeMappings["test_index"].ToDictionary(k => k.Key, v => (ITypeMapping)v.Value);
db.CreateIndex(new CreateIndexRequest("test_index")
{
Mappings = new Mappings(indexMapping)
});
Console.ReadLine();
}
class Data
{
public int Id { get; set; }
public string Name { get; set; }
}
Raw copy of index
var res = db.LowLevel.IndicesGetMapping<JObject>("test_index");
var delete = db.DeleteIndex(new DeleteIndexRequest("test_index"));
var mappings = res.Body["test_index"].ToString();
var create = db.LowLevel.IndicesCreate<JObject>("test_index", mappings);
If you really need to install the plug-in
sudo bin/plugin install delete-by-query
It worked.
Thanks a lot.
var res = db.LowLevel.IndicesGetMapping<JObject>("test_index");
var delete = db.DeleteIndex(new DeleteIndexRequest("test_index"));
var mappings = res.Body["test_index"].ToString();
var create = db.LowLevel.IndicesCreate<JObject>("test_index", mappings);

Elastic search with Nest

I am working on below code, and what I want to do is query by object itself.
For example: I have a search form, that populates objects fields such as below. Then what I want to do is to search Elastic search based on whatever user filled the form with.
ie: below, I want to query the index by searchItem object. How can I do it easily?
class Program
{
static void Main(string[] args)
{
var p = new Program();
var item1 = new Announcement() {Id=1, Title = "john", ContentText = "lorem", Bar = false, Num = 99, Foo = "hellow"};
//p.Index(item1, "add");
var searchItem = new Announcement() {Title="john",Num=99};
ElasticClient.Search<Announcement>();
Console.Read();
}
public void Index(Announcement announcement, String operation)
{
var uriString = "http://localhost:9200";
var searchBoxUri = new Uri(uriString);
var settings = new ConnectionSettings(searchBoxUri);
settings.SetDefaultIndex("test");
var client = new ElasticClient(settings);
if (operation.Equals("delete"))
{
client.DeleteById("test", "announcement", announcement.Id);
}
else
{
client.Index(announcement, "test", "announcement", announcement.Id);
}
}
private static ElasticClient ElasticClient
{
get
{
try
{
var uriString = "http://localhost:9200";
var searchBoxUri = new Uri(uriString);
var settings = new ConnectionSettings(searchBoxUri);
settings.SetDefaultIndex("test");
return new ElasticClient(settings);
}
catch (Exception)
{
throw;
}
}
}
}
You can't :)
NEST cannot infer how to best query only based on a partially filled POCO. Should it OR or AND should it do a nested term query or a term query wrapped in a has_child? You catch my drift.
Nest does have a slick feature called conditionless queries that allow you the write out to entire query like so:
ElasticClient.Search<Announcement>(s=>s
.Query(q=>
q.Term(p=>p.Title, searchItem.Title)
&& q.Term(p=>p.Num, searchItem.Num)
//Many more queries use () to group all you want
)
)
When NEST sees that the argument passed to Term is null or empty it simply wont render that part of the query.
Read more here on how this feature works http://nest.azurewebsites.net/concepts/writing-queries.html

Dynamic Array to MS SQL Database

private void getRRvalue(string DELRRNO)
{
try {
DBSFCDataContext SFC = new DBSFCDataContext();
var query = (from i in SFC.POP10500s where i.POPRCTNM == DELRRNO select new { PONO = i.PONUMBER, DATEREC = i.DATERECD, VENDID = i.VENDORID, ITEMCODE = i.ITEMNMBR, QTYBAGS = i.QTYBAGS, QTYSHIP = i.QTYSHPPD, DEPT = i.TRXLOCTN });
foreach (var r in query)
{
string[] row = {
DELRRNO,
r.PONO,
Convert.ToDateTime(r.DATEREC).ToString(),
r.VENDID,
r.ITEMCODE,
r.QTYBAGS.ToString(),
r.QTYSHIP.ToString(),
r.DEPT
};
//glbVariables.getRRNO = ;
//glbVariables.getPONO = ;
//glbVariables.getRRdateRec = ;
//glbVariables.getVendID = ;
//glbVariables.getItemNO = ;
//glbVariables.getQtyBags = ;
//glbVariables.getQtyShipped = ;
//glbVariables.getLocnCode = ;
}
SFC.Connection.Close();
}
catch (Exception ex)
{ MessageBox.Show(ex.Message.ToString()); }
}
I'm new to C#.NET and I was just thinking if I could use a dynamic array like for this code above do I need to declare a global array like this --> "public static string[] row;" so I can use this array string in another form by calling it with the data that I have stored from this function, could this happen in c#?
I need help here please anyone that is good at arrays in c#...
To get you desired results, you will have to do little more work. I explain your solution using List.
First create a class for your one query result:
public class OneRowData
{
public string DELRRNO;
public string PONO;
public string DATEREC;
public string VENDID;
public string ITEMCODE;
public string QTYBAGS;
public string QTYSHIP;
public string DEPT;
}
In your given code, create a List of OneRowData type and make it public static to access it from outside the class as well:
public static List<OneRowData> QueryResults = new List<OneRowData>();
Now in your foreach loop, create an object of OneRowData, assing values to it and add it to the List:
foreach (var r in query)
{
OneRowData Obj = new OneRowData();
//assing values to them
Obj.DATEREC = Convert.ToDateTime(r.DATEREC).ToString();
Obj.DELRRNO = DELRRNO;
Obj.DEPT = r.DEPT;
Obj.ITEMCODE = r.ITEMCODE;
Obj.PONO = r.PONO;
Obj.QTYBAGS = r.QTYBAGS.ToString();
Obj.QTYSHIP = r.QTYSHIP.ToString();
Obj.VENDID = r.VENDID;
//then add the object to your list
QueryResults.Add(Obj);
}
Now you can simply call your List any where and fetch your data like this:
foreach (OneRowData Row in QueryResults)
{
//Row.DATEREC
//Row.DELRRNO
//call them like this and use as you need
}

MongoDB select row by id and get fields (in c#) [duplicate]

first time i'm using MongoDB.
I have read this example:
SELECT a,b FROM users WHERE age=33
db.users.find({age:33}, {a:1,b:1})
But I can't translate it into C#. Can anyone help me?
I have translated your query below using the new C# driver (2.2)
var mongoClient = new MongoClient(""mongodb://127.0.0.1:27017"");
var database = mongoClient.GetDatabase("databaseName");
IMongoCollection<Users> _collection = database.GetCollection<Users>("Users");
var condition = Builders<Users>.Filter.Eq(p => p.age, 33);
var fields = Builders<Users>.Projection.Include(p => p.a).Include(p => p.b);
var results= _collection.Find(condition).Project<Users>(fields).ToList().AsQueryable();
You can do it using SetFields method of MongoCursor class, below full example:
var server = MongoServer.Create(connectionString);
var db = _server.GetDatabase("dbName");
var users = db.GetCollection("users");
var cursor = users.FindAs<DocType>(Query.EQ("age", 33));
cursor.SetFields(Fields.Include("a", "b"));
var items = cursor.ToList();
you can use anonymous class
public class User
{
public int age;
public string a;
public string b;
}
var collection = db.GetCollection<User>("Users");
var results = collection.Find(Builders<User>.Filter.Eq(user => user.age, 33))
.Project(u => new { u.a, u.b }).ToList();
//create user class
//(not sure how your class looks like)
public class User
{
public int age;
public string a;
public string b;
}
//then you can use LINQ easily
var server = MongoServer.Create(connectionString);
var db = server.GetDatabase("dbName");
var usersCollection = db.GetCollection<User>("users");
var filteredCollection = usersCollection.AsQueryable().Where(x=> x.age < 33).Where(x=> x.a != null).Contains(x=> x.b != null);

Categories