I want to count the number of items in a container.
Using SELECT value count(1) FROM tasks WHERE tasks.TaskState = 0 OR (tasks.TaskState = 4 AND tasks.RetryCount <= 3) works on the Azure Portal and now I want to do the same on the server side.
I tried to do this, but this don't work...
await this.Container.RetrieveItemsAsync<int>(new Query(CreateNumberOfTasksQuery()), cancellationToken: cancellationToken).ConfigureAwait(false);
And my query is:
"SELECT value count(1) FROM tasks WHERE tasks.TaskState = 0 OR (tasks.TaskState = 4 AND tasks.RetryCount <= 3)";
And I can't retrieve the item since int is not a reference type...
The implementation class:
public async Task<IList<T>> RetrieveItemsAsync<T>(Query query, QueryOptions queryOptions = null, CancellationToken cancellationToken = default)
where T : class
{
// Validation
SmartGuard.Check(() => query, typeof(T) != typeof(string), Properties.Resources.RES_Exception_MultiModel_Argument_UnsupportedType.Format(typeof(string)));
SmartGuard.NotNull(() => query, query);
// Logging
this.Service.Logger.LogDebug($"Retrieving items...");
// Delegate on instance
// Make sure the exceptions handler is called
IList<T> result = await CosmosDbMultiModelDatabaseExceptionHandler.HandleAsync(
OperationTarget.Item,
async () =>
{
IList<T> result = new List<T>();
Cosmos.FeedIterator<T> feedIterator = this.Instance.GetItemQueryIterator<T>(
queryDefinition: query.ToQueryDefinition(),
requestOptions: queryOptions.ToQueryRequestOptions());
while (feedIterator.HasMoreResults)
{
foreach (T item in await feedIterator.ReadNextAsync(cancellationToken).ConfigureAwait(false))
{
result.Add(item);
}
}
return result;
})
.ConfigureAwait(false);
// Logging
this.Service.Logger.LogDebug($"{result.Count} items were retrieved.");
// Result
return result;
}
This is because where T : class constraints your type must be a reference type.
You can overload your RetrieveItemsAsync method,
public async Task<IList<T>> RetrieveItemsAsync<T>(T value,Query query, QueryOptions queryOptions = null, CancellationToken cancellationToken = default)
where T : struct
{
.....
}
then you can try this:
await this.Container.RetrieveItemsAsync<int>(Int32.MaxValue,new Query(CreateNumberOfTasksQuery()), cancellationToken: cancellationToken).ConfigureAwait(false);
Related
I have this Action method which act as an API end point inside our ASP.NET MVC-5, where it search for a username and return the username Phone number and Department from Active Directory (we are serializing the object using Newtonsoft.net):-
public ActionResult UsersInfo2()
{
DomainContext result = new DomainContext();
try
{
// create LDAP connection object
DirectoryEntry myLdapConnection = createDirectoryEntry();
string ADServerName = System.Web.Configuration.WebConfigurationManager.AppSettings["ADServerName"];
string ADusername = System.Web.Configuration.WebConfigurationManager.AppSettings["ADUserName"];
string ADpassword = System.Web.Configuration.WebConfigurationManager.AppSettings["ADPassword"];
using (var context = new DirectoryEntry("LDAP://mydomain.com:389/DC=mydomain,DC=com", ADusername, ADpassword))
using (var search = new DirectorySearcher(context))
{
// create search object which operates on LDAP connection object
// and set search object to only find the user specified
// DirectorySearcher search = new DirectorySearcher(myLdapConnection);
// search.PropertiesToLoad.Add("telephoneNumber");
search.Filter = "(&(objectClass=user)(sAMAccountName=test.test))";
SearchResult r = search.FindOne();
ResultPropertyCollection fields = r.Properties;
foreach (String ldapField in fields.PropertyNames)
{
// cycle through objects in each field e.g. group membership
// (for many fields there will only be one object such as name)
string temp;
// foreach (Object myCollection in fields[ldapField])
// {
// temp = String.Format("{0,-20} : {1}",
// ldapField, myCollection.ToString());
if (ldapField.ToLower() == "telephonenumber")
{
foreach (Object myCollection in fields[ldapField])
{
result.Telephone = myCollection.ToString();
}
}
else if (ldapField.ToLower() == "department")
{
foreach (Object myCollection in fields[ldapField])
{
result.Department = myCollection.ToString();
}
}
// }
}
string output = JsonConvert.SerializeObject(result);
return Json(output,JsonRequestBehavior.AllowGet);
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return View(result);
}
now the return JSON will be as follow:-
"\"DisplayName\":null,\"Telephone\":\"123123\",\"Department\":\"IT\",\"Name\":null,\"SamAccountName\":null,\"DistinguishedName\":null,\"UserPrincipalName\":null}"
but in our case we need to return a status code beside the return json data. for example inccase there is an exception we need to return an error code,also if we are able to get the user's info we need to pass succes code 200, and so on.. so how we can achieve this?
you can try something like this
var statusCode=200;
string output = JsonConvert.SerializeObject( new { result = result, StatusCode = statusCode);
but nobody usually do this. When users call API they can check status code that HTTP Client returns, using code like this
var response = await client.GetAsync(api);
//or
var response = await client.PutAsJsonAsync(api, data);
var statusCode = response.StatusCode.ToString();
//or usually
if (response.IsSuccessStatusCode) {...}
else {...}
I have a cosmos database with 50 000 records, but the code bellow only only returns 8356. I thought setting MaxItemCount to -1 would return all of them. How can I achieve that?
public async Task<IEnumerable<T>> ReadAsync(Expression<Func<T, bool>> predicate)
{
var entityList = new List<T>();
var query = _container.GetItemLinqQueryable<T>(requestOptions: new QueryRequestOptions { MaxItemCount = -1 })
.Where(predicate).OrderByDescending(x => x.TimeStamp).AsQueryable();
using (var iterator = query.ToFeedIterator())
{
entityList.AddRange(
await iterator.ReadNextAsync());
}
return entityList;
}
You are not draining all the query results (missing the check on HasMoreResults):
public async Task<IEnumerable<T>> ReadAsync(Expression<Func<T, bool>> predicate)
{
var entityList = new List<T>();
var query = _container.GetItemLinqQueryable<T>(requestOptions: new QueryRequestOptions { MaxItemCount = -1 })
.Where(predicate).OrderByDescending(x => x.TimeStamp).AsQueryable();
using (var iterator = query.ToFeedIterator())
{
while (iterator.HasMoreResults)
{
entityList.AddRange(
await iterator.ReadNextAsync());
}
}
return entityList;
}
Reference (Intellisense docs): https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.feediterator-1?view=azure-dotnet#examples
We are using Automappers ProjectTo method to build a DTO object that is a subset of a larger database view. It is working as expected when running the actual application but we have had a problem where it doesn't give expected results when unit testing with an EF Core In-Memory database. It seems to just be giving back 0 results no matter what the query. Here is the test I am trying to run.
[Fact]
public async Task GetTemplateAdHocReportList_ReturnsOnlyTemplateReports()
{
await TestHelper.SeedFull(ReportContext); // Calls SeedAdHocReports below along with other seed methods
var results = await _sut.GetTemplateAdHocReports();
results.Where(x => !x.IsTemplate).Count().Should().Be(0);
}
This is the Seed Data:
public static async Task SeedAdHocReports(ReportContext context)
{
var reports = new AdHocReport[]
{
new AdHocReport()
{
Id = 1,
Name = "DevExtreme Example Report",
IsTemplate = true,
AdHocDataSourceId = 1,
Fields = "[{\"caption\":\"Category\",\"dataField\":\"ProductCategoryName\",\"expanded\":true,\"area\":\"row\"},{\"caption\":\"Subcategory\",\"dataField\":\"ProductSubcategoryName\",\"area\":\"row\"},{\"caption\":\"Product\",\"dataField\":\"ProductName\",\"area\":\"row\"},{\"caption\":\"Date\",\"dataField\":\"DateKey\",\"dataType\":\"date\",\"area\":\"column\"},{\"caption\":\"Amount\",\"dataField\":\"SalesAmount\",\"summaryType\":\"sum\",\"format\":{\"type\":\"currency\",\"precision\":2,\"currency\":\"USD\"},\"area\":\"data\"},{\"caption\":\"Store\",\"dataField\":\"StoreName\"},{\"caption\":\"Quantity\",\"dataField\":\"SalesQuantity\",\"summaryType\":\"sum\"},{\"caption\":\"Unit Price\",\"dataField\":\"UnitPrice\",\"format\":\"currency\",\"summaryType\":\"sum\"},{\"dataField\":\"Id\",\"visible\":false}]",
Status = true
}
};
context.AdHocReports.AddRange(reports);
await context.SaveChangesAsync();
}
Here is the GetTemplateAdHocReports method being tested
public async Task<IList<AdHocReportDto>> GetTemplateAdHocReports()
{
//This gives the expected 1 object in the unit tests:
var test = await _reportContext.AdHocReports.Where(x => x.Status && x.IsTemplate).OrderBy(x => x.Name).ToListAsync();
//This always comes back with a count of 0 even though the seed data should return 1 result
var results = await _reportContext.AdHocReports.Where(x => x.Status && x.IsTemplate).OrderBy(x => x.Name).ProjectTo<AdHocReportDto>(_mapper.ConfigurationProvider).ToListAsync();
return results;
}
Finally in case they are useful here are the constructors:
public AdHocServiceTests()
{
TestHelper = new TestHelper();
var reportOptions = TestHelper.GetMockedReportDbOptions();
ReportContext = new ReportContext(reportOptions);
_sut = new AdHocService(ReportContext, TestHelper.Mapper, TestHelper.GetMockedNiceService().Object);
}
public TestHelper()
{
var mappingConfig = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ReportDtoMapperProfile>();
});
Mapper = mappingConfig.CreateMapper(); // public property on TestHelper
}
public AdHocService(ReportContext reportContext, IMapper mapper, INiceService niceService)
{
_niceService = niceService;
_mapper = mapper;
_reportContext = reportContext;
}
So the final question is why does the "var test = " line above work, but the following "var results =" line with the ProjectTo just keeps giving back 0 results?
So I'm trying to get a little login system started. When logged in I'd like to transfer the ID from the login method to the index method.
Here's my login method
public async Task<IActionResult> Login(Models.DB.Teacher m)
{
var teacher = await _context.Teacher
.FirstOrDefaultAsync(p => p.Username == m.Username);
if (teacher == null)
{
return View(m);
}
if (m.Password.ToLower() == teacher.Password.ToLower()) //Checks if pass is the same
{
HttpContext.Session.SetInt32("sessionID", teacher.Id);
int _id = (int)HttpContext.Session.GetInt32("sessionID");
return RedirectToAction("/Index/");
}
return View(m);
}
Notice that the int _id = Session on above was just for a test. It worked in the same method.
public async Task<IActionResult> Index()
{
int _id = (int)HttpContext.Session.GetInt32("sessionID");
var teacher = await _context.Teacher
.FirstOrDefaultAsync(p => p.Id == _id);
return View(teacher);
}
This is my error message. I realise it doesn't have any value but I'm clueless as to why.
InvalidOperationException: Nullable object must have a value.
System.Nullable<T>.get_Value()
fifty.Controllers.TeachersController.Index() in TeachersController.cs
+
int _id = (int)HttpContext.Session.GetInt32("ID");
I want to invoke method durning mapping my domain class to DTO class but after many tries with LINQ to Entities or LINQ to objects i have failed and i'm getting weird different errors. Actulal error is just a "LINQ to Entities does not recognize the method 'System.String ResizeToLogoImage(System.String)' method, and this method cannot be translated into a store expression.".
Mapping method:
public async Task<SingleCategory> SingleCategoryMapping(EventerApiContext context, int id)
{
var category = await context.Category.Select(c => new SingleCategory
{
CategoryId = c.CategoryId,
CategoryName = c.CategoryName,
CityId = c.CityId,
Events = context.Event.ToList().Where(e=>e.CategoryId == id).Select(e=> new EventForSingleCategory
{
EventId = e.EventId,
EventName = e.EventName,
EventLogo = ImageProcessor.ResizeToLogoImage(e.EventDetail.EventImage.EventImageBase64)
}).ToList()
}).SingleOrDefaultAsync(c => c.CategoryId == id);
return category;
}
Method to be invoked.
public static string ResizeToLogoImage(string base64String)
{
if (base64String == null)
{
return "NULL";
}
var imageToResize = Base64ToImage(base64String);
var resizedImage = ScaleImage(imageToResize, 50, 50);
return ImageToBase64(resizedImage, imageToResize.RawFormat);
}
I know error is appearing during EventLogo property mapping but i have no more idea what to do.
Try to get the data first, before you do the Select statement. I suspect that it is trying to execute ResizeToLogoImage on the database :)