I have a storage table in Azure with the following primary and row keys (not really, just an example) and retrieve the whole table as a list of TableEntities:
"partitionkey", "00"
"partitionkey", "01"
"partitionkey", "10"
"partitionkey", "11"
"partitionkey", "20"
"partitionkey", "21"
When I query the list like so:
var myItem =
(from item in list
where item.RowKey == "00"
select item).FirstOrDefault();
myItem returns null. The same is true if I query for RowKey == "01".
But when I query by RowKey alone with any string which does NOT have a leading "0", I get the expected result. Also, if I query using any PartitionKey and the RowKey HAS a leading "0":
var myItem =
(from item in list
where item.PartitionKey == "partitionkey" && item.RowKey == "00"
select item).FirstOrDefault();
I will also get the expected result.
If RowKeys in Azure Table Storage are strings, why does a string with a leading "0" matter?
Has anybody else run into this and if so, is it a bug?
Has anybody else run into this and if so, is it a bug?
According to your description, it seems that there is no suitable entity in the list when
myItem returns null. You could try to output the entities in the list
foreach (var item in list)
{
Console.WriteLine("{0}, {1}", item.PartitionKey, item.RowKey,);
}
I test with following code, it works correctly on my side. I can't reproduce the issue you mentioned
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("storage connectionstring");
// Create the table client.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
// Create the CloudTable object that represents the "test" table.
CloudTable table = tableClient.GetTableReference("test");
TableQuery<TableEntity> query = new TableQuery<TableEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey",QueryComparisons.Equal, "partitionkey"));
var list = table.ExecuteQuery(query);
var myItem = (from item in list
where item.RowKey == "00"
select item).FirstOrDefault();
Test result:
Related
I want to create a function that gets the first value of a table field if two other field values match the two given function parameters.
I thought this would be easy. But I found nothing in the internet or M documentation that could solve this.
I don't know if I have to loop through a record or if there is a top level function.
= (val1 as text, val2 as text) as text =>
let
result = if [Field1] = val1 and [Field2] = val2 then [Field3] else ""
in
result
As far as I understand your wish, table and column names are hard coded (i.e. you intend to apply the function only for specific table). Then you may use following approach:
// table
let
t1 = #table({"Field1"}, List.Zip({{"a".."e"}})),
t2 = #table({"Field2"}, List.Zip({{"α".."ε"}})),
join = Table.Join(t1&t1,{}, t2&t2,{}),
add = Table.AddIndexColumn(join, "Field3", 0, 1)
in
add
// func
(val1 as text, val2 as text) => Table.SelectRows(table, each [Field1] = val1 and [Field2] = val2)[Field3]{0}
// result
func("d","β") //31
please guide, i am able to work with Dynamic Group by , but when selecting non agrigated fields , i get the following error
No property or field 'name' exists in type 'IGrouping`2'
var result311 = (IQueryable)gle1.temptable.Where(a => a.IsAllowed == false && a.Code == "r01");
var result = result311.GroupBy("new (name, FirstAmountOriginal, SecondAccounting)", "it")
.Select("new (it.name,Sum(FirstAmountOriginal) as FirstAmountOriginalx, Sum(SecondAccounting) as SecondAccountingx)");
Please guide
Firstly, you should not group by the fields you want to aggregate and secondly, the grouping creates a grouping Key consisting of the fields you group by (in this case one), so you must address this key afterwards:
var result = result311.GroupBy("new(name)", "it")
.Select(#"new (it.Key.name,
Sum(FirstAmountOriginal) as FirstAmountOriginalx,
Sum(SecondAccounting) as SecondAccountingx)");
I need a Linq statement that will select all from a table where a field contains all elements in a list<String> while searching other fields for the entire string regardless of words.
It's basically just a inclusive word search on a field where all words need to be in the record and string search on other fields.
Ie I have a lookup screen that allows the user to search AccountID or Detail for the entire search string, or search clientID for words inclusive words, I'll expand this to the detail field if I can figure out the ClientId component.
The complexity is that the AccountId and Detail are being searched as well which Basically stops me from doing the foreach in the second example due to the "ors".
Example 1, this gives me an the following error when I do query.Count() afterwards:
query.Count(); 'query.Count()' threw an exception of type 'System.NotSupportedException' int {System.NotSupportedException}
+base {"Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator."} System.SystemException {System.NotSupportedException}
var StrList = searchStr.Split(' ').ToList();
query = query.Where(p => p.AccountID.Contains(searchStr) || StrList.All(x => p.clientID.Contains(x)) || p.Detail.Contains(searchStr));
Example 2, this gives me an any search word type result:
var StrList = searchStr.Split(' ').ToList();
foreach (var item in StrList)
query = query.Where(p => p.AccountID.Contains(searchStr) || p.clientID.Contains(item) || p.Detail.Contains(searchStr));
Update
I have a table with 3 fields, AccountID, ClientId, Details
Records
Id, AccountID, CLientId, Details
1, "123223", "bobo and co", "this client suxs"
2, "654355", "Jesses hair", "we like this client and stuff"
3, "456455", "Microsoft", "We love Mircosoft"
Search examples
searchStr = "232"
Returns Record 1;
searchStr = "bobo hair"
Returns no records
searchStr = "bobo and"
Returns Record 1
searchStr = "123 bobo and"
Returns returns nothing
The idea here is:
if the client enters a partial AccountId it returns stuff,
if the client wants to search for a ClientId they can type and cancel down clients by search terms, ie word list. due to the large number of clients the ClientID Will need to contain all words (in any order)
I know this seems strange but it's just a simple interface to find accounts in a powerful way.
I think there are 2 solutions to your problem.
One is to count the results in memory like this:
int count = query.ToList().Count();
The other one is to not use All in your query:
var query2 = query;
foreach (var item in StrList)
{
query2 = query2.Where(p => p.clientID.Contains(item));
}
var result = query2.Union(query.Where(p => p.AccountID.Contains(searchStr) || p.Detail.Contains(searchStr)));
The Union at the end acts like an OR between the 2 queries.
First Table is the View and Second is the result I want
This below query works fine
List<BTWStudents> students = (from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
select new BTWStudents
{
StudentId = V.StudentId
Amount= V.PaymentMethod == "Cashier Check" ? V.Amount: "0.00"
}).Distinct().ToList();
But I changed it to List to add string formatting(see below)
List<BTWStudents> students = (from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
select new {V}).ToList().Select(x => new BTWStudents
{
StudentId = V.StudentId
Amount= V.PaymentMethod == "Cashier Check" ? String.Format("{0:c}",V.Amount): "0.00"
}).Distinct().ToList();
With this Second Query I get this
Why is distinct not working in the second query?
When working with objects (in your case a wrapped anonymous type because you are using Select new {V} rather than just Select V), Distinct calls the object.Equals when doing the comparison. Internally, this checks the object's hash code. You'll find in this case, the hash code of the two objects is different even though the fields contain the same values. To fix this, you will need to override Equals on the object type or pass a custom IEqualityComparer implementation into the Distinct overload. You should be able to find a number of examples online searching for "Distinct IEqualityComparer".
Try this (moved your distinct to the first query and corrected your bugged if/then/else):
List<BTWStudents> students = (from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
select new {V}).Distinct().ToList().Select(x => new BTWStudents
{
classId = V.Class.HasValue ? V.Class.Value : 0,
studentName = V.StudentName,
paymentAmount = V.PaymentMethod == "Cashier Check" ? String.Format("{0:c}",x.V.AmountOwed): "0.00"
}).ToList();
You can get around using Distinct all together if you Group by StudentID
var studentsGroupedByPayment =
(from V in db.vwStudentCoursesSD
where classIds.Contains(V.Class.Value)
group V by V.StudentId into groupedV
select new
{
StudentID = groupedV.Key,
Amount = string.Format("{0:C}",
groupedV.First().PaymentMethod == "Cashier Check" ?
groupedV.First().Amount : 0.0)
}
).ToList();
I want to update and insert some records based on a csv I read. The insert is not a problem, but how to update a bunch of data in a single statement? I have not clear how to join them.
Update Item
Set
Name = t.Name
From
Item i, TextFile t
Where
i.ItemNo = t.ItemNo
For the Name = t.Name I created an private Item UpdateItem(Item originalItem, Item newItem) in which the logic for updating is present.
I want to know to to call this functions and perform an db.SubmitChanges() with the changed records.
Any help appreciated.
I'm making the assumption that TextFile is an in memory collection of objects that you've read from the CSV file and Items is a Table in the data context from your database. In that case I don't think you will be able to do an actual join without first fetching all of the items from the database into an in memory collection as well -- which may be a costly operation. The sample below selects just those items and its matching new name from the text file into a new collection, then iterates through that collection and sets the name on the item. It won't use your UpdateItem method.
var textFile = ...collection of objects from CSV...
var textIDs = textFile.Select( t => t.ItemNo );
using (var db = new DataContext())
{
var toUpdate = db.Items
.Where( i => textIDs.Contains( i.ItemNo ) )
.ToList() // <--- this will force the query
.Select( i => new
{
Item = i,
NewName = textFile.Where( t => t.ItemNo == i.ItemNo )
.Single()
.Name
});
foreach (var item in toUpdate)
{
item.Item.Name = item.NewName;
}
db.SubmitChanges();
}