Linq query on IReliableDictionary - c#

I have done a bunch of looking and messing with code and I haven't found a way to do Linq Queries against the IReliableDictionary. I know it's not the same as standard IDictionary, but I was curious if anyone has had any luck. I'm starting to think it's just not possible unfortunately.

Currently, there's no normal way to do a linq query on a reliable dictionary. That being said, there are a few things you can do. As previously stated, the reason the CreateEnumerableAsync method exists is because service fabric pages reliable dictionaries to disk, but if you know that the underlying collection is small and you're okay with a performance hit, then the following class will work.
public static class AsyncEnumerableExtensions
{
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerator">enumerator to convert</param>
/// <param name="ct">cancellation token for the async operations</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static async Task<IList<TValType>> ToListAsync<TValType>(
this IAsyncEnumerator<TValType> enumerator,CancellationToken ct, ITransaction tx)
{
IList<TValType> ret = new List<TValType>();
while (await enumerator.MoveNextAsync(ct).ConfigureAwait(false))
{
ret.Add(enumerator.Current);
}
return ret;
}
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerator">enumerator to convert</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static Task<IList<TValType>> ToListAsync<TValType>(
this IAsyncEnumerator<TValType> enumerator, ITransaction tx)
{
return enumerator.ToListAsync(CancellationToken.None,tx);
}
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerable">enumerator to convert</param>
/// <param name="ct">cancellation token for the async operations</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static Task<IList<TValType>> ToListAsync<TValType>(this IAsyncEnumerable<TValType> enumerable,
CancellationToken ct, ITransaction tx)
{
return enumerable.GetAsyncEnumerator().ToListAsync(ct,tx);
}
/// <summary>
/// Converts the collection to a list
/// </summary>
/// <typeparam name="TValType">value type of the collection</typeparam>
/// <param name="enumerable">enumerator to convert</param>
/// <param name="tx">tx to enforce that this is called in a transactional context</param>
/// <returns>a list containing all elements in the origin collection</returns>
public static Task<IList<TValType>> ToListAsync<TValType>(this IAsyncEnumerable<TValType> enumerable, ITransaction tx)
{
return enumerable.GetAsyncEnumerator().ToListAsync(tx);
}
}
You could also implement your own custom enumerators and extension methods to perform linq-query like operations on your data in an efficient manner. I have written a few that I would like to release but they need some polish first. I have a sneaking feeling that the service fabric team might already be on it, but if or when that happens your guess is as good as mine.

Looks like MS removed the ability to do linq queries in the latest SF release.

If you need to handle operations that are more involved than simple GetByKey(), you would need to explicitly create a local collection of it via the IReliableDictionary.CreateEnumerable() method, which you would then be able to query similar to the following example from the comments in this discussion :
IAsyncEnumerable<KeyValuePair<int, string="">> enumerable = await myDictionary.CreateEnumerableAsync(tx);
using (IAsyncEnumerator<KeyValuePair<int, string="">> e = enumerable.GetAsyncEnumerator())
{
while (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
{
doSomething(e.Current);
}
}
This may not fit your scenario at all, but it seems that it's likely the only way to perform any kind of "advanced queries".

Right LINQ will not work with IAsyncEnumerator
var wgEnumerable = await voteDictionary.CreateEnumerableAsync(tx);
using(IAsyncEnumerator<KeyValuePair<string, int>> enumerator = wgEnumerable.GetAsyncEnumerator())
{
while(await enumerator.MoveNextAsync(CancellationToken.None))
{
//Do something
}
}

It is possible to use Async Linq after converting SerivceFabric's IAsyncEnumerable to a dotnet one.
Please refer to this answer:
Convert IReliableDictionary to IList

Related

Can I use <inheritdoc cref> to reference the XML summary of another variable?

When I'm writing functions for my project, and more specifically, their XML documentation comments, I find myself repeating the comments for a specific parameter often. This leads to misleading documentation sometimes (as copy pasting usually does...).
This is a simple example I thought of, which represents the real problem.
/// <summary>
/// The number that should be doubled
/// </summary>
private static float myNumber = 10f;
/// <summary>
/// Multiplies a number by 2
/// </summary>
/// <param name="number"><inheritdoc cref="myNumber"/></param>
/// <returns>The number multiplied by 2</returns>
private static float MultiplyByTwo(float number)
{
return number * 2f;
}
In this line /// <param name="number"><inheritdoc cref="myNumber"/></param>, I would like to have the text "The number that should be doubled", but it's not showing up. Maybe I don't understand the use of inheritdoc completely.
What I mean by showing up is this. Visual Studio should show the documentation of number in that box:
This is what it should look like (without copy pasting the text):
So, is there a way to reference a different variable in XML documentation comments?
In Visual Studio 16.8.4 I'm able to use <inheritdoc>'s path attribute to do this.
/// <summary>
/// The number that should be doubled
/// </summary>
private static float myNumber = 10f;
/// <summary>
/// Multiplies a number by 2
/// </summary>
/// <param name="number"><inheritdoc cref="myNumber" path="/summary"/></param>
/// <returns></returns>
private static float MultiplyByTwo(float number)
{
return number * 2f;
}
In the path attribute, / selects the 'root' node and then summary is the node to select within that node.
Result:
The path attribute uses XPath syntax, which you can find more about here.
You can use it to do some great stuff if you're careful; I regularly use it when implementing the Try[...] pattern.
For example:
/// <summary>
/// This throws!
/// </summary>
/// <param name="param1">This is a parameter.</param>
/// <param name="param2">This is another parameter!</param>
/// <exception cref="InvalidOperationException"/>
public string ExampleThatCanThrow(int param1, float param2)
{
throw new InvalidOperationException();
}
/// <summary>
/// This never throws!
/// </summary>
/// <inheritdoc cref="ExampleThatCanThrow(int, float)" path="/*[not(self::exception)]"/>
public bool TryExample(int param1, float param2, out string? result)
{
result = "No throwing here!";
return true;
}
Normally when using <inheritdoc> for the TryExample method in this way, it would show that it could throw InvalidOperationException. Using the path attribute, I've filtered it so only the nodes that don't match the name of exception will be inherited.
/: Matches the root node.
*: Matches any child node.
[ and ]: Matches any node that meets the conditions of the contained predicate.
not(): Matches any node that doesn't meet the conditions of the expression within the parentheses.
self::exception: Matches the current node if it has the name of exception.
This results in the below:
In addition, you can use this functionality to more easily show the exceptions that can be thrown by a method without typing them out explicitly:
/// <summary>
/// Validates a file in some way.
/// </summary>
/// <param name="filePath">A full path to the file to be validated.</param>
/// <inheritdoc cref="File.OpenRead(string)" path="/exception"/>
private static void ValidateFile(string filePath)
{
using FileStream file = File.OpenRead(filePath);
// Validation code...
}
This above use of <inheritdoc> will cause the tooltip on the method to show that it can throw all of the exceptions that the System.IO.File.OpenRead method can throw. Just be careful that you ensure necessary validation exceptions are actually thrown and accounted for.

<typeparamref> to a parameter of another class in C# XML doc

Is there a way to refer to the generic parameter of another class? I know I can do this with the current class using <typeparamref>.
One example would be when writing the documentation of an async methods. These return Task and people would commonly need to refer to TResult. Look at the "Return Value" on this page, for instance. They used <paramref> which obviously didn't do the job.
/// <returns>
/// A task that represents the asynchronous create operation.
/// The value of the <paramref name="TResult"/> parameter contains the number of documents created.
/// </returns>
public static async Task<int> CreateDocumentsAsync(string filename)
What shall I use instead of <paramref>?
I don't quite understand your question, so I'll post a couple of examples that may help you in regards to generics with the XML documentation.
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
private void IDoSomething<T>(T obj)
{
}
/// <summary>
/// See type <see cref="T:My.Namespace.MyObject"/>
/// </summary>
private MyObject MyObj;
public class MyObject
{
}
I do not think that is possible (and the example with System.IO.Stream.ReadAsync seems to be an example of an invalid reference, see my comment to the question above).
The rest of this post is not an answer to your question but a suggestion for a more correct documentation:
In your concrete example, you could refer to the Result property inside Task<> instead of the impossible reference to the type parameter TResult itself. That is:
/// <returns>
/// The value of the <see cref="Task{_}.Result" /> property contains ...
/// </returns>
public static async Task<int> CreateDocumentsAsync(string filename)
If you do not like the _ hack above, you can do:
/// <returns>
/// The value of the <see cref="Task{Int32}.Result" /> property contains ...
/// </returns>
public static async Task<int> CreateDocumentsAsync(string filename)
Of course, you can refer to int with <see cref="Int32" />.

Implementing a LinkedHashTable in C# with given Table C#

For an assignment for school I have to create a LinkedHashTable in C#. The teacher has given me a Table interface that I must go by, but I'm a little lost as to whether or not I'm making a HashTable/Dictionary in my LinkedHashTable class as if it was a data member and doing whatever management to make it linked.
What I had originally did was make a:
Dictionary<Key, List<Value>> hash;
in the LinkedHashTable class I made and the get, put, and contains methods I implemented pertained to that structure. Here is the table interface:
interface Table<Key, Value> : IEnumerable<Key>
{
/// <summary>
/// Add a new entry in the hash table. If an entry with the
/// given key already exists, it is replaced without error.
/// put() always succeeds.
/// (Details left to implementing classes.)
/// </summary>
/// <param name="k">the key for the new or existing entry</param>
/// <param name="v">the (new) value for the key</param>
void Put(Key k, Value v);
/// <summary>
/// Does an entry with the given key exist?
/// </summary>
/// <param name="k">the key being sought</param>
/// <returns>true iff the key exists in the table</returns>
bool Contains(Key k);
/// <summary>
/// Fetch the value associated with the given key.
/// </summary>
/// <param name="k">The key to be looked up in the table</param>
/// <returns>the value associated with the given key</returns>
/// <exception cref="NonExistentKey">if Contains(key) is false</exception>
Value Get(Key k);
}
In the test file, he's got stuff like:
ht.Put("Chris", "Swiss");
try
{
foreach (String first in ht)
{
Console.WriteLine("5");
Console.WriteLine(first + " -> " + ht.Get(first));
}
The whole foreach loop makes me think that I'm supposed to implement my class in a way such that it is a LinkedHashTable in itsself, not just some class having a HashTable as a member. Unfortunately, I'm pretty confused as to how to do this. Any suggestions would be nice.
Perhaps some reading on interface might help answer your question. Some class that you create may need to implement the given interface.
http://msdn.microsoft.com/en-us/library/87d83y5b.aspx

Data Caching in ASP.Net

I need to fill some dropdown boxex from some reference data. i.e City List, Country List etc. I need to fill it in various webforms. I think, we should cache this data in our application so that, we don't hit database on every form. I am new to caching and ASP.Net. Please suggest me how to do this.
I always add the following class to all my projects which give me easy access to the Cache object. Implementing this, following Hasan Khan's answer would be a good way to go.
public static class CacheHelper
{
/// <summary>
/// Insert value into the cache using
/// appropriate name/value pairs
/// </summary>
/// <typeparam name="T">Type of cached item</typeparam>
/// <param name="o">Item to be cached</param>
/// <param name="key">Name of item</param>
public static void Add<T>(T o, string key, double Timeout)
{
HttpContext.Current.Cache.Insert(
key,
o,
null,
DateTime.Now.AddMinutes(Timeout),
System.Web.Caching.Cache.NoSlidingExpiration);
}
/// <summary>
/// Remove item from cache
/// </summary>
/// <param name="key">Name of cached item</param>
public static void Clear(string key)
{
HttpContext.Current.Cache.Remove(key);
}
/// <summary>
/// Check for item in cache
/// </summary>
/// <param name="key">Name of cached item</param>
/// <returns></returns>
public static bool Exists(string key)
{
return HttpContext.Current.Cache[key] != null;
}
/// <summary>
/// Retrieve cached item
/// </summary>
/// <typeparam name="T">Type of cached item</typeparam>
/// <param name="key">Name of cached item</param>
/// <param name="value">Cached value. Default(T) if item doesn't exist.</param>
/// <returns>Cached item as type</returns>
public static bool Get<T>(string key, out T value)
{
try
{
if (!Exists(key))
{
value = default(T);
return false;
}
value = (T)HttpContext.Current.Cache[key];
}
catch
{
value = default(T);
return false;
}
return true;
}
}
From other question of yours I read that you're using 3 layer architecture with dal, business and presentation layer.
So I assume that you have some data access class. Ideal thing to do would be to have a cached implementation of the same class and do caching in that.
Eg: If you have an interface IUserRepository then UserRepository class would implement it and add/delete/update entries in db via methods then you can also have CachedUserRepository which will contain instance of UserRepository object and on get methods it will first look into the cache against some key (derived from method parameters) and if the item is found then it will return it otherwise you call the method on internal object; get the data; add to cache and then return it.
Your CachedUserRepository will also have instance of cache object obviously. You can look at http://msdn.microsoft.com/en-us/library/18c1wd61(v=vs.85).aspx for details on how to use Cache object.

How do I reference a C# keyword in XML documentation?

<see cref="switch" />, for example, doesn't work - I get the compilation warning: XML comment on ... has syntactically incorrect cref attribute 'switch'
Context for those who are interested...
/// <summary>Provides base functionality for hand-coded abstractions of API method wrappers, mostly those that abstract over
/// parameters that are required to be JSON-encoded.</summary>
public class FacebookArgs : Dictionary<String, Object>
{
/// <summary>Initializes an instance of <see cref="FacebookArgs" />.</summary>
public FacebookArgs() { }
/// <summary>Intializes an instance of <see cref="FacebookArgs" />, that contains elements copied from <paramref name="dictionary "/>.</summary>
/// <param name="dictionary"></param>
public FacebookArgs(IDictionary<String, Object> dictionary)
: base(dictionary) { }
/// <summary>Gets or sets the value associated with the specified key.</summary>
/// <param name="key">The key of the value to get or set.</param>
/// <returns>The value associated with the specified key.</returns>
/// <remarks>This implementation hides the base indexer implementation such that specifying a key that does not exist returns null rather than throwing a <see cref="KeyNotFoundException" />.</remarks>
public new Object this[String key]
{
get
{
Object value;
if (this.TryGetValue(key, out value)) return value;
else return null;
}
set { base[key] = value; }
}
/// <summary>In derived classes, provides specialized serialization logic for specific properties contained in this object.</summary>
/// <param name="key">The key of the property to serialize.</param>
/// <param name="args">A reference to a dictionary of arguments that will be passed directly to a <see cref="FacebookRequest" /> object.</param>
/// <remarks>
/// <para>This method allows specialized serialization logic, such as JSON encoding, to be applied to specific properties.</para>
/// <para>To implement, use a <c>switch</c> (<c>Select</c> in VB.NET) statement to filter based on <paramref name="key" /> and provide the property-specific logic.
/// The resulting value should then be added to <paramref name="args" /> using the same <paramref name="key "/>.
/// </para>
/// <para>Properties that do not require additional processing (strings, integral values, etc) should be ignored.</para>
/// </remarks>
protected virtual void SerializeProperty(String key, ref IDictionary<String, Object> args) { }
/// <summary>Returns a dictionary of key/value pairs suitable to be passed a <see cref="FacebookRequest" /> object.</summary>
/// <returns>A dictionary of key/value pairs suitable to be passed a <see cref="FacebookRequest" /> object.</returns>
/// <remarks>This method calls the <see cref="SerializeProperty" /> for each key in the object, which allows property-specific processing
/// to be done on any property.</remarks>
/// <seealso cref="SerializeProperty" />
public IDictionary<String, Object> GetArgs()
{
IDictionary<String, Object> args = new Dictionary<String, Object>();
foreach (String key in this.Keys)
{
this.SerializeProperty(key, ref args);
if (!args.ContainsKey(key) && this[key] != null)
{
args.Add(key, this[key]);
}
}
return args;
}
}
The tag in question can be found in the <remarks> tag for SerializeProperty. I'm erring on the side of verbose documentation. I also plan on providing some <example>s, I just haven't gotten around to it yet.
cref is meant to refer to another member - a class, a method etc.
What would you expect it to link to in this case? In general, what do you want the overall effect to be?
According to this excellent XML doc guide, the <see> tag has an undocumented attribute langword:
<see langword="switch" />
Would that help you? It might be worth trying it just to see what it does.
If you just want to use a normal hyperlink, use href instead of cref:
<see href="http://msdn.microsoft.com/en-us/library/06tc147t.aspx">switch</see>

Categories

Resources