using the "ScanOperator.In" for DynamoDB in ASP.NET - c#

I'm using the AWS SDK for .NET, and I'm trying to perform a "scan" operation using the "in" operator.
The ScanCondition takes in three arguments, but I'm not sure what the last argument [the values] should be.
Is it an array of strings? (this returns empty, when it should return results)
Is it a comma-delimited list of strings? (this throws an error saying it could not convert a list of strings into a string)
I've tried a number of different things, and nothing has worked.
public void GetUsers()
{
AmazonDynamoDBClient client = new AmazonDynamoDBClient("key", "secret", Amazon.RegionEndpoint.GetBySystemName("systemEndpoint");
DynamoDBContext context = new DynamoDBContext(client);
var results = context.Scan<User>(new ScanCondition("ID", ScanOperator.In, list /* what goes here? */));
}

The values argument should be of type object[].
In your example, (assuming your list is of type int[] or List), it needs to be cast to type object[] first.
var objectValues = list.Select(x => (object)x).ToArray();
var results = context.Scan<User>(new ScanCondition("ID", ScanOperator.In, objectValues));
It's a known usability issue with the API. If your ID property were of type string, it would work as you'd expect.

As the documentation states the object needed is AttributeValueList.
So you will need to wrap your strings as AttributeValues before passing them to the Scan command

Related

List to IEnumerable in a Async method

I have a method:
public Task<IEnumerable<MyDetails>> HandleAsync(...)
Within this method, I simply build a list of items.
IEnumerable<MyDetails> myDetails = new List<MyDetails> {
new MyDetails{ Name = 'John' },
new MyDetails{ Name = 'James' },
new MyDetails{ Name = 'Anne' },
};
And then return the result.
return Task.FromResult(insuraceTypeDetails);
In a code review, I'm being asked to use var instead of IEnumerable<MyDetails>
However, when attempting that, I get an error on my return:
Cannot convert type Threading.Tasks.Task<List> to
Threading.Tasks.Task<IEnumerable>
I thought this would be fine, but the compiler will not allow it. Can I use var here? Or am I correctly explicitly telling the compiler what we need?
In a code review, I'm being asked to use var instead of IEnumerable<MyDetails>
var will infer the type the variable from the intialization, in this cast a List<MyDetails>. But as you have discovered, you need the variable to be an IEnumerable<MyDetails> to match the return type.
You could do something goofy like convert it to an IEnumerable:
return Task.FromResult(insuraceTypeDetails.AsEnumerable());
or do an explicit cast:
return Task.FromResult((IEnumbrable<MyDetails>)insuraceTypeDetails);
but those are just working around a dogmatic coding style. There's absolutely nothing wrong with explicitly declaring the variable type, especially when using the inferred type does not work.
Use IEnumerable<MyDetails> and explain to your colleagues why var is not the right choice here.

C# Converting an anonymous object with nested collection into an IEnumerable - preferably using the 'as' keyword

My code receives an anonymous object created by another method. I would like to access and iterate through the nested collection in this object. I was trying to come up with several different ways to cast it using the 'as' keyword but no avail.
Here is the code which creates the object:
var result = new object();
foreach (var item in items)
{
result = new
{
Variants = item.Value.Select(m => m.Item2).GroupBy(n => n.Item1).Select(r => new
{
Name = r.Key,
Items = r.Select(p => new
{
Value = p.Item2.Trim(),
Text = p.Item2.Substring(0, p.Item2.LastIndexOf('_')).Trim()
}).Where(p => !string.IsNullOrEmpty(p.Text)).ToList()
})
};
}
Visual Studio gives me the following signature when I hover over the variable which received this anonymous type:
{ Variants = {System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Linq.IGrouping<string, System.Tuple<string, string>>, <>f__AnonymousType1<string, System.Collections.Generic.List<<>f__AnonymousType2<string, string>>>>} }
In short: I would like to access the Text fields of the collection.
Here is the QuickWatch window showing the structure and data of this object:
QuickWatch Window
Would appreciate any help!
PS: Cannot change the code in the sending method.
If you don't have a static type of a class you can't cast to it. For anonymous types having its type means you either have it locally in the method or get as parameter of a generic method - neither is the case here.
You options are really limited to some sort of reflection to dig into anonymous class. The easiest way would be to let runtime deal with reflection by relying on dynamic like ((dynamic)myVariable).Text.

Convert neo4j list of integers to C# array

I have a small C# application that queries a Neo4j database. The queries work fine, but I'm having trouble converting arrays of integers to an appropriate C# list type. It just seems that they should be in a proper List/Array/etc. on the C# side.
Here is the query that I run - it returns the correct results, but I'm not smart enough to get the returned list portion into a proper C# list-type object. Here is the code that is running:
using (var driver = GraphDatabase.Driver("bolt:validURL, AuthTokens.Basic("username", "password")))
// using (var session = driver.Session())
{
var result = session.Run("MATCH (c:Climate) WHERE c.koppen = 'BSh' RETURN c.koppen AS koppen, c.counties AS counties");
foreach (var record in result)
{
var koppen = record["koppen"].As<string>();
var counties = record["counties"];
}
}
}
}
}
The record[counties] is a list of a integers with - so it seems that I should easily be able to put it into a C# list object that I can iterate through. I need to do that in order to process each county and display results. C# is pretty new for me, so thanks for your help in letting me connect these two languages!
EDIT: No responses, so I tried a new approach - to simplify things, I am no longer returning the koppen value - just the list of counties (which is where the problem lies). I found some code in the Neo4j manual, and tried it:
public List<int> GetCounties()
{
using (var driver = GraphDatabase.Driver("bolt://validURL", AuthTokens.Basic("username", "password")))
using (var session = driver.Session())
{
return session.ReadTransaction(tx =>
{
var result = tx.Run("MATCH (c:Climate) WHERE c.koppen = 'BSh' RETURN c.counties");
var a = result.Select(Record => Record[0].As<int>()).ToList();
return a;
});
}
}
}
Now I'm getting an exception:
System.InvalidCastException occurred
HResult=0x80004002
Message=Unable to cast object of type 'System.Collections.Generic.List`1[System.Object]' to type 'System.IConvertible'.
Source=
StackTrace:
The exception occurs on the line ending with the toList() statement. Sorry for my not understanding the conversions that need to occur between Neo4j list results and C# lists/arrays/etc. I'm happy to try any suggestions that I get!

Convert Array to Type Array

I'm creating a generic object from DB data:
object[] data = new object[dataReader.FieldCount];
dataReader.GetValues(data);
T t = (T)Activator.CreateInstance(typeof(T), data);
But, types with no constructor error on the third line. I want to add an if:
if (typeof(T).GetConstructor(data.TypesOf()) != null)
data.TypesOf() is actually an array - Type[] - that contains all types of the objects in data.
What is the equivalent to data.TypesOf() that really works?
Or do I need to iterate data and build it myself?
I'm assuming your object[] is containing values that are, for example, an int, a string and a float, and you are trying to resolve a constructor of the form public T(int,string,float). To get the types, you could use:
var types = Array.ConvertAll(data, x => x.GetType());
But that won't actually help you much here, since that is pretty-much what Activator.CreateInstance(typeof(T), data) has already tried to do - so if Activator failed, I don't see that it is obvious that you're going to do any better - unless the key difference is that the constructor is non-public and you are going to supply some BindingFlags.
Personally, though, I would suggest that it is easier to bind by name than by position; there are tools like dapper that will do all of that for you, allowing you to use simply:
var data = conn.Query<SomeType>(sql, args).ToList();
for example:
int userId = 12345;
var users = conn.Query<User>("select * from Users where Id = #userId",
new {userId}).SingleOrDefault();
As far as I understood you are trying to get types of elememnts of an object array. So you can do something like:
var ctorArgsTypes = data.Select(d => d.GetType()).ToArray()
var ctor = typeof(T).GetConstructor(ctorArgsType);
// check if appropriate ctor exists
if (ctor == null)
throw something
T t = (T)Activator.CreateInstance(typeof(T), data);
When you look at the Activator.CreateInstance(Type, Object[]) method, for the Object[] paramter :
An array of arguments that match in number, order, and type the
parameters of the constructor to invoke. If args is an empty array or
null, the constructor that takes no parameters (the default
constructor) is invoked.
So maybe in your case, your data object is not typed for each value (if getting from a DB or a file). You need to find a way to "type" your objects in your data array.
Just use Type.GetTypeArray(object[]).
https://msdn.microsoft.com/en-us/library/system.type.gettypearray(v=vs.110).aspx

Is there any way of knowing the content of an IQueryable object without using Reflection?

I have to work with a given class "QueryGenerator" that generates dynamic queries from selected Tables and Columns by the user using a StringConnection and a Provider. Anyways, i don't have to know the implementation of the class but i have to use it and i'm stock.
At the end, the "QueryGenerator" returns the result query as an object, the only thing that i know (because i use Reflector on the class) is that i can do an IQueryable cast on that query result. Here is an example:
var result = (IQueryable)myQueryGenerator.Result;
And for knowing the content of result, i have to use Reflection.
So, is there any better way of finding out the content of result , and, for example, fill a DataSet with it?
No, there isn't.
IQueryable could return objects of different types (e.g. if you query against an array of objects). In this extreme case you would need to determine the type for each individual item in the enumerated query as you access them.
Example code to demonstrate this scenario:
object[] objs = new object[3]{ "string", 78, DateTime.Now };
var q = objs.AsQueryable().Skip(1).Take(2);
foreach( var o in q )
{
var t = o.GetType();
}

Categories

Resources