DataTable Select() with Guids - c#

I am trying to boild my treeview at runtime from a DataTable that is returned from a LINQ query. The Fields returned are:
NAME = CaseNoteID | ContactDate | ParentNote
TYPE = Guid | DateTime | Guid
The ParentNote field matches a entry in the CaseNoteID column. The Select(filter) is giving me a runtime error of Cannot find column [ea8428e4]. That alphanumeric is the first section of one of the Guids. When I step thru my code filter = "ParentNote=ea8428e4-1274-42e8-a31c-f57dc2f189a4"
What am I missing?
var tmpCNoteID = dr["CaseNoteID"].ToString();
var filter = "ParentNote="+tmpCNoteID;
DataRow[] childRows = cNoteDT.Select(filter);

Try enclosing the GUID with single quotes:
var filter = "ParentNote='"+tmpCNoteID+"'";

I know this is an old thread, but I wanted to add an addendum to it. When using the IN operator with a Guid (ex: ParentNote IN ( , , etc. ) ) then single quotes are no longer accepted. In that case, the CONVERT method (suggested by granadaCoder) is necessary. (Single quotes raise an exception about comparing a Guid to a string with the '=' operator... which we actually aren't using.)
Details: I inherited some legacy code that built a large filter string in the format: MyColumn = '11111111-2222-3333-4444-555555555555' OR MyColumn = '11111111-2222-3333-4444-555555555555' ....
When the number of guids (and, therefore the number of OR clauses) got to be too large, this caused a stack overflow exception. By replacing the numerous OR clauses with an IN clause, I was able to set the filter without an exception. But using an IN clause means having to use the CONVERT approach.

this should work :
var tmpCNoteID = dr["CaseNoteID"].ToString();
var filter = "ParentNote=\""+tmpCNoteID+"\"";
DataRow[] childRows = cNoteDT.Select(filter);

Here is one method I use:
MyStrongDataSet ds = new MyStrongDataSet();
Guid myUuid = new Guid("11111111-2222-3333-4444-555555555555");
System.Data.DataRow[] rows = ds.MyStrongTable.Select("MyGuidProperty = (CONVERT('" + myUuid.ToString("N") + "', 'System.Guid'))");
//Fish out a single row if need be and cast to a strong row
if (null != rows)
{
if (rows.Length > 0)
{
MyStrongDataSet.MyStrongTableRow returnRow = rows[0] as MyStrongDataSet.MyStrongTableRow;
return returnRow;
}
}
return null;
Here is a slight variation:
string filterSql = "MyGuidProperty ='{0}'";
filterSql = string.Format(filterSql, Guid.NewGuid().ToString("D"));

Related

Dynamic linq backslash in where clause

I use System.Linq.Dynamic to query entities with dynamic 'where' expressions. I'm querying object that has property "newValue" of string type. Exemplary value would be : "{\"ProcessId\":764, \"ProcessLength\":1000}".
I can't use == because I want to find all hits where the property contains "ProcessId:764", regardless on the rest of the string. The thing is, that stored string contains escape sign "\" and double quotes and I can't figure out what it should like exactly..
dbContext.Processes.Where("#newValue.Contains(\"ProcessId\":764\")") brings error, however dbContext.Processes.Where("#newValue.Contains(\":764\")") works correctly. I guess it must be something with backslashes or double quotes in my query but can't figure it out on my own..
There are two things to note here:
If you know at compile time the column that should be queried (i.e., newValue), just use standard Linq: var list = items.Where(i => i.NewValue.Contains("904")).ToList().
If you do want to use dyanmic Linq, What you'd usually want is to apply Where on some column, e.g. Where("SomeColumn.Contains("something")"), or Where("SomeColumn.Contains(#0)", new string[] {"something"}).
So, in your case, this should work: items.Where("newValue.Contains(\"904\")").
Doing Where("#newValue.Contains("something")") doesn't really make sense, since #newValue would be parsed as a string literal. See also this comment on a similiar question.
Here' a quick example:
public static void Main(string[] args)
{
var items = new []
{
new { Id = "1", Title = "ProcessId: 123"},
new { Id = "4", Title = "ProcessId: 456"},
new { Id = "7", Title = "ProcessId: 789"},
}.ToList();
// returns null, because the string "Title" doesn't contain the string "7"
var res1 = items.Where("#0.Contains(\"7\")", new string[] {"Title"}).FirstOrDefault();
// works - returns the 3rd element of the array
var res2a = items.Where("Title.Contains(#0)", new string[] {"ProcessId: 789"}).FirstOrDefault();
var res2b = items.Where("Title.Contains(\"ProcessId: 789\")").FirstOrDefault();
}
#HeyJude Thanks for the effort, but I still can't get it to work. It has somehow gone wronger and now I can't even fetch correct rows giving only ProcessId number..
Let me give you more detailed description of my setup. In the database there's a table with column "NewValue", I use this column to store json string of current (for the time of creating row in the table) representation of some object e.g. object Process. So the column stores for example string of {"ProcessId":904,"ProcessLength":1000}. To fetch this data from db I create collection of table's records: var items = (from l in db.JDE_Logs
join u in db.JDE_Users on l.UserId equals u.UserId
join t in db.JDE_Tenants on l.TenantId equals t.TenantId
where l.TenantId == tenants.FirstOrDefault().TenantId && l.Timestamp >= dFrom && l.Timestamp <= dTo
orderby l.Timestamp descending
select new //ExtLog
{
LogId = l.LogId,
TimeStamp = l.Timestamp,
TenantId = t.TenantId,
TenantName = t.TenantName,
UserId = l.UserId,
UserName = u.Name + " " + u.Surname,
Description = l.Description,
OldValue = l.OldValue,
NewValue = l.NewValue
});. Then I query it to find matching rows for given ProcessId number e.g. query = "#NewValue.Contains(\"904,)\")";
items = items.Where(query);
This should fetch back all records where NewValue column contains the query string, but this doesn't work. It compiles and 'works' but no data are fetched or fetched are only those records where 904 appears later in the string. Sounds stupid but this is what it is.
What should the query string look like to fetch all records containing "ProcessId":904?

Compare two datatables to find matching values

I have 2 data tables. Each one has one column and I want to compare them and get same values on them but it does not work.
This is my code:
string CurrentRequestUrl = (HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.ToString());
DataTable dt_Item = ERP.BLL_Menu_Item.Custom_Item_ID(CurrentRequestUrl);
DataTable dt2_SysRole = ERP.BLL_Sys_User_Role.Custom_Role(Convert.ToInt64(App.UserID));
var dtOne = (dt_Item.AsEnumerable()).ToList();
var dtTwo = (dt2_SysRole.AsEnumerable()).ToList();
IEnumerable<DataRow> objIntersectResult = ((dtOne).Intersect((dtTwo))).ToList();
How can I find the matching values?
Intersect does not work here because on DataRow it just compares references. Because all rows are different references you get an empty list. Instead you want to compare values. Therefore you can use Join. But which row do you want to return from both tables? If you want both rows you could create an anonymous type of both:
var objJoinResult = from rowItem in dt_Item.AsEnumerable()
join rowSysRole in dt2_SysRole.AsEnumerable()
on rowItem.Field<string>("ColumnName") equals rowSysRole.Field<string>("ColumnName")
select new { rowItem, rowSysRole };
Output:
foreach (var both in objJoinResult)
{
Console.WriteLine("rowItem:{0} rowSysRole:{1}",
string.Join(",", both.rowItem.ItemArray),
string.Join(",", both.rowSysRole.ItemArray));
}

Is there a way to access the columns in a Dapper FastExpando via string or index?

I am pulling in a Dapper FastExpando object and want to be able to reference the column names dynamically at run time rather than at design/compile time. So I want to be able to do the following:
var testdata = conn.Query("select * from Ride Where RiderNum = 21457");
I want to be able to do the following:
foreach( var row in testdata) {
var Value = row["PropertyA"];
}
I understand that I can do:
var Value = row.PropertyA;
but I can't do that since the name of the property i'm going to need won't be known until runtime.
The answer from this SO Question doesn't work. I still get the same Target Invocation exception. So...
Is there any way to do what I want to do with a Dapper FastExpando?
Sure, it is actually way easier than that:
var sql = "select 1 A, 'two' B";
var row = (IDictionary<string, object>)connection.Query(sql).First();
row["A"].IsEqualTo(1);
row["B"].IsEqualTo("two");
Regarding the portion of the title "or index?" - I needed to access results by index since the column names being returned changed sometimes, so you can use a variation of Sam Saffron's answer like this:
var sql = "select 1, 'two'";
var row = (IDictionary<string, object>)connection.Query(sql).First();
row.Values.ElementAt(0).IsEqualTo(1);
row.Values.ElementAt(1).IsEqualTo("two");
There a simple way to access fields direct below sample
string strConexao = WebConfigurationManager.ConnectionStrings["connection"].ConnectionString;
conexaoBD = new SqlConnection(strConexao);
conexaoBD.Open();
var result = conexaoBD.Query("Select Field1,Field2 from Table").First();
//access field value result.Field1
//access field value result.Field2
if (result.Field1 == "abc"){ dosomething}

LINQ Query for Filter Result

Experts,
I have a datatable with two columns:
1) One is Decimal
2) One is String
I write my filter query like:
var iFilterResult = from c in dataTable1.AsEnumerable()
where c.Field<string>("ACM_ACCOUNT_CODE").Contains(txtFindPrePaidExpenses.Text)
&& c.Field<string>("ACM_ACCOUNT_DESC").Contains(txtFindPrePaidExpenses.Text)
select new
{
ACM_ACCOUNT_CODE = c.Field<string>("ACM_ACCOUNT_CODE"),
ACM_ACCOUNT_DESC = c.Field<string>(" ACM_ACCOUNT_DESC")
};
gvSearchAccountGL.DataSource = iFilterResult;
gvSearchAccountGL.DataBind(); "
Here dataTable1 is Datatable Having Column
ACM_ACCOUNT_CODE of decimal type
ACM_ACCOUNT_DESC of string type.
use like Query for filter.
But it is not working
You're trying to use ACM_ACCOUNT_CODE as a string field - but you've said it's a decimal field.
It's not clear why you'd expect a decimal field to contain the same value as the description field. If you really want this, you could use:
c.Field<decimal>("ACM_ACCOUNT_CODE")
.ToString()
.Contains(txtFindPrePaidExpenses.Text)
... but I suspect you should rethink what the query is trying to do.

Convert DataTable to LINQ: Unable to query multiple fields

Importing a spreadsheet I have filled a DataTable object with that data and returns expected results.
Attempting to put this into a format I can easily query to search for problem records I have done the following
public void Something(DataTable dt)
{
var data = from row in dt.AsEnumerable()
select row["Order"].ToString();
}
Works as expected giving me a list of orders. However I cannot add other fields to this EnumerableRowCollection. Attempting to add other fields as follows gives me an error
public void Something(DataTable dt)
{
// row["Version"] throws an error on me
var data = from row in dt.AsEnumerable()
select row["Order"].ToString(), row["Version"].ToString();
}
Error: "A local variable named 'row' cannot be declared in this scope because it would give a different meaning to 'row' which is already used in a 'child' scope to donate something else"
I'm thinking I need to alias the column name but I'm having no luck. What am I missing here?
It sounds like you're writing a bad select statement. Try the following:
public void Something(DataTable dt)
{
var data = from row in dt.AsEnumerable()
select new {
Order = row["Order"].ToString(),
Something = row["Something"].ToString(),
Customer = row["Customer"].ToString(),
Address = row["Address"].ToString()
};
}
That will create a new collection of Anonymously Typed objects that you can iterate over and use as needed. Keep in mind, though, that you want be able to return data from the function. If you need that functionality, you need to create a concrete type to use (in place of anonymous types).
I think you should use select new like this query for example:
var q = from o in db.Orders
where o.Products.ProductName.StartsWith("Asset") &&
o.PaymentApproved == true
select new { name = o.Contacts.FirstName + " " +
o.Contacts.LastName,
product = o.Products.ProductName,
version = o.Products.Version +
(o.Products.SubVersion * 0.1)
};
You probably want the following.
var data = from row
in dt.AsEnumerable()
select new { Order = row["Order"].ToString(), Version = row["Version"].ToString() };

Categories

Resources