2

I am using Cosmos 3.3 sdk and below is the code to write to my container.

 public void WriteErrorLogs(Error entity, string collectionName)
        {
            try
            {
                Container container = cosmosclient.GetContainer(databaseName, collectionName);
                entity.LogID = Guid.NewGuid().ToString();          
                container.CreateItemAsync<Error>(entity, new PartitionKey(entity.LogID));
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

The container in cosmos look like this having partition key as id

enter image description here

the Error class is like this

  public class Error
    {
        [JsonProperty(PropertyName = "id")]
        public string LogID { get; set; }

        public System.DateTime DateStamp { get; set; }
        public string EID { get; set; }
        public string Message { get; set; }
        public string StackTrace { get; set; }
        public string InnerException { get; set; }

I defined partition key to be the LogID which is a guid.The method needs to be synchronous due to the code constraint. Not sure where I am wrong but while debugging always getting" container error CS0103: The name 'container' does not exist in the current context" and logs are not getting created.Any help would be really appretiated,Thanks

David Makogon
  • 69,407
  • 21
  • 141
  • 189
  • The error your getting is pretty self explanatory, the variable `container` does not exist in the context you're using it. In fact, from the code you posted it only exists inside your `try` clause. – Javier Silva Ortíz Nov 12 '19 at 12:23
  • Add a debug point and see what is inside container? – Sajeetharan Nov 12 '19 at 12:52
  • I had a debugger and not getting anything inside container infact since its not in context its not showing as an object.Are you guys saying I need to define the statement above try?Thats surprise to me? – Gaurav Bhardwaj Nov 12 '19 at 14:33

2 Answers2

3

You are doing a fire-and-forget, the CreateItemAsync is a Task, an async operation, and you are not awaiting it.

public async Task WriteErrorLogs(Error entity, string collectionName)
{
    try
    {
        Container container = cosmosclient.GetContainer(databaseName, collectionName);
        entity.LogID = Guid.NewGuid().ToString();          
        await container.CreateItemAsync<Error>(entity, new PartitionKey(entity.LogID));
    }
    catch (Exception ex)
    {
        throw ex;
    }

}

And anywhere you call WriteErrorLogs you need to await it too.

For example:

await WriteErrorLogs(entity, "myerrorcollection")

During your build process, there might be Warnings pointing at this specific issue.

EDIT: Based on OP comment, adding how to force the operation to be sync, but this is not recommended, you might potentially end with deadlocks, see https://stackoverflow.com/a/24298425/5641598

public void WriteErrorLogs(Error entity, string collectionName)
{
    try
    {
        Container container = cosmosclient.GetContainer(databaseName, collectionName);
        entity.LogID = Guid.NewGuid().ToString();          
        container.CreateItemAsync<Error>(entity, new PartitionKey(entity.LogID)).GetAwaiter().GetResult();
        // or ItemResponse<Error> response = container.CreateItemAsync<Error>(entity, new PartitionKey(entity.LogID)).Result;
        // or container.CreateItemAsync<Error>(entity, new PartitionKey(entity.LogID)).Wait();
    }
    catch (Exception ex)
    {
        throw ex;
    }

}
Matias Quaranta
  • 13,907
  • 1
  • 22
  • 47
  • Thanks for your explanation however I want to run this as a synchronous operation due to the log hierarchy from where the code is getting called.For example this function is getting called from 100 other functions and those 100 from another 200.Its a huge legacy code base and doing it all async is really a pain. – Gaurav Bhardwaj Nov 12 '19 at 21:21
  • 1
    Calling async code in a sync fashion is really not recommended in .NET, you are locking threads and you can certainly get into a deadlock situation. Having said that, I have edited the answer to include how to run this synchronously. – Matias Quaranta Nov 12 '19 at 23:49
  • I implemented all three ways and here's what happening and same end result.Logs are not getting written.For all the ways you mentioned te page is loading for long and nothing happenning.No exception also,not sure how to catch the exception in such case. – Gaurav Bhardwaj Nov 13 '19 at 16:44
  • 1
    You can be running into a deadlock, that is why locking an async operation is not recommended. That will basically make this operation either not complete, or maybe never get there, maybe the thread is already locked when `.Result` is being called. Either resolve the deadlock or correctly consume async code in async manner. – Matias Quaranta Nov 13 '19 at 17:22
-1

I found the issue.It was a threading issue as told by Matias.I explicitly run the task as Task.Run (async..functioncall).wait() and then in the function call defined createItemasync as a sync call.