How to mock ExecuteReaderAsync in .NET Framework c# - nuget

I need to mock the ExecuteReaderAsync for my project.
Actually in my project I am dealing all the db related query using procedure so that I have created generic repo to handle the db query using the below code.
Below one is the repository to make the db connection and execute the stored procedure .
public async Task<DbDataReader> ExecGetWithStoreProcedure(string storeProcedureName, params object[] parameters)
{
try
{
var command = _dbContext.Database.Connection.CreateCommand();
command.Connection.Open();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = storeProcedureName;
foreach (var item in parameters)
{
command.Parameters.Add(item);
}
return await command.ExecuteReaderAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
throw ex;
}
}
Now when I am writing the test case so noticed that DB is not getting mock it's returning the actual data from database. I have tried to mock the DbCommand , DbDataReader but still not able to mock it successfully. Here is the below code
Below one is the service class.
public async Task<HttpResponseModel<FormulationReviewCommentsResults>> GetDashboardFormulationReviewComments(int PageSize, int PageNumber, string userName)
{
List<Tbl_FormulationReviewComments> list = new List<Tbl_FormulationReviewComments>();
var result = new FormulationReviewCommentsResults();
try
{
using (_unitOfWork = new UnitOfWorkRMM(new PlutoContextRMM(DBConstants.connectionName)))
{
var reader = await _unitOfWork.DashboardRepos.ExecGetWithStoreProcedure(DBConstants.USP_MST_GET_DashboardReviewComments,
new SqlParameter(DBConstants.PageSize, SqlDbType.Int) { SqlValue = PageSize },
new SqlParameter(DBConstants.PageNumber, SqlDbType.Int) { SqlValue = PageNumber },
new SqlParameter(DBConstants.userName, SqlDbType.NVarChar) { SqlValue = userName }).ConfigureAwait(false);
while (reader.Read())
{
var comments = new Tbl_FormulationReviewComments();
comments.Id = int.Parse(reader.GetValue(0).ToString());
comments.Name = reader.GetValue(1).ToString();
comments.FormulationDetailId = int.Parse(reader.GetValue(2).ToString());
comments.Comment = reader.GetValue(3).ToString();
comments.FormulationDetailId = int.Parse(reader.GetValue(4).ToString());
comments.FormulationReferenceNo = reader.GetValue(5).ToString();
comments.VersionNo =reader.GetValue(6).ToString();
comments.TotalRecords = int.Parse(reader.GetValue(7).ToString());
list.Add(comments);
}
result.FormulationReviewComments = list;
result.TotalRecords = list.Count > 0 ? list[0].TotalRecords : 0;
return _httpResponse.HandleReturnResponse(result, MessagesConstants.CommonErrorMessage, false);
}
}
catch (Exception ex)
{
_logger.Error(ex, strLoggerName);
return _httpResponse.HandleReturnResponse(result, MessagesConstants.CommonErrorMessage, false);
}
}
Mocking the DataReader and all realted things using the below code.
public static void GetDashBoard3()
{
string[] fieldNames = { "Id", "Name", "FormulationDetailId", "Comment", "FormulationDetailId", "FormulationReferenceNo", "VersionNo", "TotalRecords" };
List<FormulationReviewCommentsResults> resultModel = new List<FormulationReviewCommentsResults>();
List<Tbl_FormulationReviewComments> items = new List<Tbl_FormulationReviewComments>();
items.Add(new Tbl_FormulationReviewComments
{
TotalRecords = 1,
Comment = "",
CommentAssignedTo = "",
CommentClosedBy = "",
CommentClosedDate = DateTime.Now,
CommentCreatedBy = "",
CommentCreatedDate = DateTime.Now,
CommentDueDate = DateTime.Now,
CommentRepliedBy = "",
CommentRepliedDate = DateTime.Now,
CommentsReplied = "",
CommentUpdatedBy = "",
CommentUpdatedDate = DateTime.Now,
CreatedBy = "",
CreatedDate = DateTime.Now,
FormulationDetailId = 12313,
FormulationRawMaterialId = 123,
FormulationRawMaterialSubComponentId = 12321,
FormulationReferenceNo = "",
Id = 1,
isClosed = false,
IsDeleted = false,
isReplied = false,
ManufacturerId = 123,
ManufacturerName = "",
MarketId = 123,
MarketName = "",
Name = "",
RawMaterialId = 123,
RawMaterialName = "",
RegulationId = 123,
ReviewComments = "sdfsadf",
ReviewedBy = "",
ReviewedDate = DateTime.Now,
StatusCode = "202",
StatusId = 1,
StatusName = "",
SubComponentName = "",
SupplierId = 1,
SupplierName = "",
SupplierRawMaterialSubComponentDetailId = 123,
TradeName = "",
});
resultModel.Add(new FormulationReviewCommentsResults
{
FormulationReviewComments = items,
TotalRecords = 1
});
Mock<DbProviderFactory> mockedDataReader = new Mock<DbProviderFactory>();
var commandMock = new Mock<IDbCommand>();
var readerMock = new Mock<IDataReader>();
commandMock.Setup(m => m.ExecuteReader()).Returns(readerMock.Object).Verifiable();
var parameterMock = new Mock<IDbDataParameter>();
commandMock.Setup(m => m.CreateParameter()).Returns(parameterMock.Object);
commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())).Verifiable();
commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())).Verifiable();
commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())).Verifiable();
var connectionMock = new Mock<IDbConnection>();
connectionMock.Setup(m => m.CreateCommand()).Returns(commandMock.Object);
//-----------------------------------------------------
readerMock.Setup(x => x.Read()).Returns(() => true);
readerMock.Setup(x => x.FieldCount).Returns(8);
readerMock.Setup(m => m.GetName(0)).Returns("id"); // the first column name
readerMock.Setup(m => m.GetName(1)).Returns("Name");
readerMock.Setup(m => m.GetName(2)).Returns("FormulationDetailId");
readerMock.Setup(m => m.GetName(3)).Returns("Comment");
readerMock.Setup(m => m.GetName(4)).Returns("FormulationDetailId");
readerMock.Setup(m => m.GetName(5)).Returns("FormulationReferenceNo");
readerMock.Setup(m => m.GetName(6)).Returns("VersionNo");
readerMock.Setup(m => m.GetName(7)).Returns("TotalRecords");
readerMock.Setup(x => x.GetValue(0)).Returns((int id) => resultModel[0].FormulationReviewComments[0].Id);
readerMock.Setup(x => x.GetValue(1)).Returns((string Name) => resultModel[0].FormulationReviewComments[0].Name);
readerMock.Setup(x => x.GetValue(2)).Returns((int FormulationDetailId) => resultModel[0].FormulationReviewComments[0].FormulationDetailId);
readerMock.Setup(x => x.GetValue(3)).Returns((string Comment) => resultModel[0].FormulationReviewComments[0].Comment);
readerMock.Setup(x => x.GetValue(4)).Returns((int FormulationDetailId) => resultModel[0].FormulationReviewComments[0].FormulationDetailId);
readerMock.Setup(x => x.GetValue(5)).Returns((string FormulationReferenceNo) => resultModel[0].FormulationReviewComments[0].FormulationReferenceNo);
readerMock.Setup(x => x.GetValue(6)).Returns((string VersionNo) => resultModel[0].FormulationReviewComments[0].VersionNo);
readerMock.Setup(x => x.GetValue(7)).Returns((int TotalRecords) => resultModel[0].FormulationReviewComments[0].TotalRecords);
readerMock.SetupSequence(m => m.Read()).Returns(true).Returns(false);
}
Here is the final unit test cases for the above
[Theory]
[InlineData(1, 1, "asdf")]
public async Task GetDashboardFormulationReviewComments1New(int a, int b, string c)
{
//var dd = (DbDataReader)dataReader;
DashboardReposReturns.GetDashBoard3();
var context2 = _unitOfWork.Setup(dd => dd.DashboardRepos.ExecGetWithStoreProcedure(It.IsAny<string>()));
// Act
var result = await _dashboardRepos.GetDashboardFormulationReviewComments(a, b, c);
//Assert
Assert.NotNull(result);
Assert.NotNull(result.Data);
Assert.True(result.Data.TotalRecords == 0);
}

Related

Insert/Update 50 records from JSON file to SQL Table taking too much in ASP.NET MVC EF core

I am doing insert/update records from JSON file to SQL table in the single action method. I am inserting only 50 records but it takes too much time. I am new to ASP.NET Core. Don't know whether my too much for each loop creates the issue or my database logic. Please can anybody help me to correct this issue?
I am reading json and based on custom mapping, I am doing insert or update to table column from json object values.
Please look into my below code
[HttpPost]
public IActionResult InsertProductDetails()
{
int getcountProductName = (from gcPN in _context.K360MappingMasters
where gcPN.K360Catalog == "Name" && gcPN.ApiContent == baseurl
select gcPN).Count();
if (getcountProductName == 0)
{
return Json(new { Status = "error", Message = "Required ProductName catalog not yet mapped , unable to insert productdetails" });
}
else if (getcountProductName == 1)
{
try
{
using WebClient wc = new WebClient();
string contentString = wc.DownloadString(baseurl);
List<Dictionary<string, string>> ListJsonProductContent = new List<Dictionary<string, string>>();
List<string> ListProductsCheck = new List<string>();
var token = JToken.Parse(contentString);
if (token.Type == JTokenType.Array) // "["
{
ListJsonProductContent = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(contentString);
}
else if (token.Type == JTokenType.Object) // "{"
{
var ObjectResponse = JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString);
foreach (var x in ObjectResponse)
{
string key = x.Key.ToString();
string val = x.Value.ToString();
foreach (var dicItemML in JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(val))
{
ListJsonProductContent.Add(dicItemML);
}
}
}
List<K360MappingMaster> ListMappedDataDb = new List<K360MappingMaster>();
var VLinqQuery = from KMM in _context.K360MappingMasters
where KMM.ApiContent != null && KMM.ApiContent == baseurl
select KMM;
ListMappedDataDb = VLinqQuery.ToList();
foreach (var dicItemML in ListJsonProductContent)
{
Dictionary<string, string> updItem = new Dictionary<string, string>();
foreach (var itemMl in dicItemML)
{
var catalogProductsCheck = _context.CatalogProducts.ToList();
var result = catalogProductsCheck.Select(s => s.Name).ToList().Contains(itemMl.Value);
if (result == true)
ListProductsCheck.Add(itemMl.Value.ToString());
if (ListMappedDataDb.Select(s => s.ApiCatalog).ToList().Contains(itemMl.Key))
{
foreach (K360MappingMaster data in ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key))
{
if (updItem.ContainsKey(data.K360Catalog))
{
if (data.K360Catalog == "Specification")
{
updItem[data.K360Catalog] += "<p>" + itemMl.Key + " :" + itemMl.Value + "<p>";
}
else
{
updItem[data.K360Catalog] += " " + itemMl.Value;
}
}
else
{
if (data.K360Catalog == "Specification")
{
updItem.Add(data.K360Catalog, "<p>" + itemMl.Key + " :" + itemMl.Value + "<p>");
}
else
{
updItem.Add(data.K360Catalog, itemMl.Value);
}
}
}
}
dicItemML.Remove(itemMl.Key);
}
foreach (var itemM2 in updItem)
{
dicItemML.Add(itemM2.Key, itemM2.Value);
}
}
List<CatalogProduct> ListKp = new List<CatalogProduct>();
foreach (var dicItem in ListJsonProductContent)
{
CatalogProduct Ctgkp = new CatalogProduct
{
Name = dicItem.ContainsKey("Name") ? dicItem["Name"] : "No Product",
Slug = dicItem.ContainsKey("Name") ? string.Concat(dicItem["Name"].Where(c => !char.IsWhiteSpace(c))).ToLower(CultureInfo.CurrentCulture) : "No Slug",
Price = dicItem.ContainsKey("Price") ? decimal.Parse(dicItem["Price"], CultureInfo.InvariantCulture) : default,
ShortDescription = dicItem.ContainsKey("ShortDescription") ? dicItem["ShortDescription"] : null,
Description = dicItem.ContainsKey("Description") ? dicItem["Description"] : null,
Specification = dicItem.ContainsKey("Specification") ? dicItem["Specification"] : null,
RatingAverage = dicItem.ContainsKey("RatingAverage") ? double.Parse(dicItem["RatingAverage"], CultureInfo.InvariantCulture) : null,
MetaTitle = dicItem.ContainsKey("MetaTitle") ? dicItem["MetaTitle"] : null,
MetaKeywords = dicItem.ContainsKey("MetaKeywords") ? dicItem["MetaKeywords"] : null,
MetaDescription = dicItem.ContainsKey("MetaDescription") ? dicItem["MetaDescription"] : null,
Sku = dicItem.ContainsKey("Sku") ? dicItem["Sku"] : null,
Gtin = dicItem.ContainsKey("Gtin") ? dicItem["Gtin"] : null,
NormalizedName = dicItem.ContainsKey("NormalizedName") ? dicItem["NormalizedName"] : null,
StockQuantity = dicItem.ContainsKey("StockQuantity") ? int.Parse(dicItem["StockQuantity"], CultureInfo.InvariantCulture) : 50,
ReviewsCount = dicItem.ContainsKey("ReviewsCount") ? int.Parse(dicItem["ReviewsCount"], CultureInfo.InvariantCulture) : default,
DisplayOrder = dicItem.ContainsKey("DisplayOrder") ? int.Parse(dicItem["DisplayOrder"], CultureInfo.InvariantCulture) : 1,
OldPrice = dicItem.ContainsKey("OldPrice") ? decimal.Parse(dicItem["OldPrice"], CultureInfo.InvariantCulture) : null,
SpecialPrice = dicItem.ContainsKey("SpecialPrice") ? decimal.Parse(dicItem["SpecialPrice"], CultureInfo.InvariantCulture) : null,
SpecialPriceStart = dicItem.ContainsKey("SpecialPriceStart") ? DateTimeOffset.Parse(dicItem["SpecialPriceStart"], CultureInfo.InvariantCulture) : null,
SpecialPriceEnd = dicItem.ContainsKey("SpecialPriceEnd") ? DateTimeOffset.Parse(dicItem["SpecialPriceEnd"], CultureInfo.InvariantCulture) : null,
IsPublished = true,
PublishedOn = DateTimeOffset.Now,
CreatedById = 10,
IsDeleted = false,
CreatedOn = DateTimeOffset.UtcNow,
LatestUpdatedOn = DateTimeOffset.UtcNow,
LatestUpdatedById = 10,
HasOptions = false,
IsVisibleIndividually = true,
IsFeatured = true,
IsCallForPricing = false,
IsAllowToOrder = true,
StockTrackingIsEnabled = true
};
ListKp.Add(Ctgkp);
}
using (var transaction = _context.Database.BeginTransaction())
{
try
{
int numCpTotal = 0;
var catalogProducts = _context.CatalogProducts.ToList();
var config = new MapperConfiguration(cfg => cfg.CreateMap<CatalogProduct, CatalogProduct>()
.ForMember(c => c.Id, opt => opt.Ignore()));
var mapper = config.CreateMapper();
_context.ChangeTracker.AutoDetectChangesEnabled = false;
foreach (var kp in ListKp)
{
var existingRootProduct = _context.CatalogProducts.SingleOrDefault(x => x.Name == kp.Name);
if (existingRootProduct == null)
{
if (ListProductsCheck.Count > 0)
{
var firstItem = ListProductsCheck.ToList();
foreach (var item in firstItem)
{
_context.CatalogProducts.RemoveRange(_context.CatalogProducts.Where(c => c.Name == item));
_context.CoreEntities.RemoveRange(_context.CoreEntities.Where(c => c.Name == item));
_context.SaveChanges();
}
}
_context.CatalogProducts.Add(kp);
_context.SaveChanges();
CoreEntity ce = new CoreEntity
{
Name = kp.Name,
Slug = string.Concat(kp.Name.Where(c => !char.IsWhiteSpace(c))).ToLower(CultureInfo.CurrentCulture),
EntityId = kp.Id,
EntityTypeId = "Product",
};
_context.CoreEntities.Add(ce);
}
else
{
mapper.Map<CatalogProduct, CatalogProduct>(kp, existingRootProduct);
}
}
(from q in _context.K360MappingMasters
where q.ApiContent == baseurl
select q).ToList().ForEach(x => x.InsertStatusFlag = true);
_context.ChangeTracker.DetectChanges();
numCpTotal = _context.SaveChanges();
_context.ChangeTracker.AutoDetectChangesEnabled = true;
transaction.Commit();
return Json(new { Status = "success", Message = "No conflicts. " + numCpTotal + " product details saved." });
}
catch (Exception ex)
{
transaction.Rollback();
return Json(new { Status = "warning", Message = ex.Message });
throw new Exception();
}
}
}
catch (Exception ex)
{
return Json(new { Status = "warning", Message = ex.Message });
throw new Exception();
}
}
else
{
return RedirectToAction("Index");
}
}

How to do both Add and Update in Entity Framework ASP.NET Core?

I want to do both updates and add in the same action method in ASP.NET Core by Entity Framework Core, but after making an addition to a list of records in the database, I cannot update the same records to the table. It always creates a new set of records.
What is my mistake? Can anybody please help me?
[HttpPost]
public IActionResult InsertProductDetails()
{
using WebClient wc = new WebClient();
string contentString = wc.DownloadString(baseurl);
List<Dictionary<string, string>> ListJsonProductContent = new List<Dictionary<string, string>>();
var token = JToken.Parse(contentString);
if (token.Type == JTokenType.Array) // "["
{
ListJsonProductContent = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(contentString);
}
else if (token.Type == JTokenType.Object) // "{"
{
var ObjectResponse = JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString);
foreach (var x in ObjectResponse)
{
string key = x.Key.ToString();
string val = x.Value.ToString();
foreach (var dicItemML in JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(val))
{
ListJsonProductContent.Add(dicItemML);
}
}
}
List<K360MappingMaster> ListMappedDataDb = new List<K360MappingMaster>();
var VLinqQuery = from KMM in _context.K360MappingMasters
where KMM.ApiUrl != null && KMM.ApiUrl == baseurl
select KMM;
ListMappedDataDb = VLinqQuery.ToList();
foreach (var dicItemML in ListJsonProductContent)
{
Dictionary<string, string> updItem = new Dictionary<string, string>();
foreach (var itemMl in dicItemML)
{
if (ListMappedDataDb.Select(s => s.ApiCatalog).ToList().Contains(itemMl.Key))
{
if (updItem.ContainsKey(ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault()))
{
if (ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault() == "Specification")
{
updItem[ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault()] += "<p>" + itemMl.Key + " :" + itemMl.Value + "<p>";
}
else
{
updItem[ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault()] += " " + itemMl.Value;
}
}
else
{
if (ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault() == "Specification")
{
updItem.Add(ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault(), "<p>" + itemMl.Key + " :" + itemMl.Value + "<p>");
}
else
{
updItem.Add(ListMappedDataDb.Where(s => s.ApiCatalog == itemMl.Key).Select(s => s.K360Catalog).FirstOrDefault(), itemMl.Value);
}
}
}
dicItemML.Remove(itemMl.Key);
}
foreach (var itemM2 in updItem)
{
dicItemML.Add(itemM2.Key, itemM2.Value);
}
}
List<CatalogProduct> ListKp = new List<CatalogProduct>();
foreach (var dicItem in ListJsonProductContent)
{
try
{
CatalogProduct Ctgkp = new CatalogProduct
{
Name = dicItem.ContainsKey("Name") ? dicItem["Name"] : "No Product",
Slug = dicItem.ContainsKey("Name") ? string.Concat(dicItem["Name"].Where(c => !char.IsWhiteSpace(c))).ToLower() : "No Slug",
Price = dicItem.ContainsKey("Price") ? decimal.Parse(dicItem["Price"], CultureInfo.InvariantCulture) : default,
ShortDescription = dicItem.ContainsKey("ShortDescription") ? dicItem["ShortDescription"] : null,
Description = dicItem.ContainsKey("Description") ? dicItem["Description"] : null,
Specification = dicItem.ContainsKey("Specification") ? dicItem["Specification"] : null,
RatingAverage = dicItem.ContainsKey("RatingAverage") ? double.Parse(dicItem["RatingAverage"], CultureInfo.InvariantCulture) : null,
MetaTitle = dicItem.ContainsKey("MetaTitle") ? dicItem["MetaTitle"] : null,
MetaKeywords = dicItem.ContainsKey("MetaKeywords") ? dicItem["MetaKeywords"] : null,
MetaDescription = dicItem.ContainsKey("MetaDescription") ? dicItem["MetaDescription"] : null,
Sku = dicItem.ContainsKey("Sku") ? dicItem["Sku"] : null,
Gtin = dicItem.ContainsKey("Gtin") ? dicItem["Gtin"] : null,
NormalizedName = dicItem.ContainsKey("NormalizedName") ? dicItem["NormalizedName"] : null,
StockQuantity = dicItem.ContainsKey("StockQuantity") ? int.Parse(dicItem["StockQuantity"], CultureInfo.InvariantCulture) : 50,
ReviewsCount = dicItem.ContainsKey("ReviewsCount") ? int.Parse(dicItem["ReviewsCount"], CultureInfo.InvariantCulture) : default,
DisplayOrder = dicItem.ContainsKey("DisplayOrder") ? int.Parse(dicItem["DisplayOrder"], CultureInfo.InvariantCulture) : 1,
OldPrice = dicItem.ContainsKey("OldPrice") ? decimal.Parse(dicItem["OldPrice"], CultureInfo.InvariantCulture) : null,
SpecialPrice = dicItem.ContainsKey("SpecialPrice") ? decimal.Parse(dicItem["SpecialPrice"], CultureInfo.InvariantCulture) : null,
SpecialPriceStart = dicItem.ContainsKey("SpecialPriceStart") ? DateTimeOffset.Parse(dicItem["SpecialPriceStart"], CultureInfo.InvariantCulture) : null,
SpecialPriceEnd = dicItem.ContainsKey("SpecialPriceEnd") ? DateTimeOffset.Parse(dicItem["SpecialPriceEnd"], CultureInfo.InvariantCulture) : null,
IsPublished = true,
PublishedOn = DateTimeOffset.Now,
CreatedById = 10,
IsDeleted = false,
CreatedOn = DateTimeOffset.UtcNow,
LatestUpdatedOn = DateTimeOffset.UtcNow,
LatestUpdatedById = 10,
HasOptions = false,
IsVisibleIndividually = true,
IsFeatured = true,
IsCallForPricing = false,
IsAllowToOrder = true,
StockTrackingIsEnabled = true
};
ListKp.Add(Ctgkp);
}
catch (Exception ex)
{
TempData["Exceptionmsg"] = ex;
return RedirectToAction("Index");
throw;
}
}
int numP = 0;
try
{
using (var transaction = _context.Database.BeginTransaction())
{
int getcount = (from gcM in _context.CatalogProducts
select gcM).Count();
if (getcount == 0)
{
_context.CatalogProducts.AddRange(ListKp);
_context.SaveChanges();
}
else
{
var catalogProducts = (from gcM in _context.CatalogProducts select gcM).ToList();
for (int i = 0; i < catalogProducts.Count; i++)
{
catalogProducts[i].Name = ListKp[i].Name;
catalogProducts[i].Price = ListKp[i].Price;
catalogProducts[i].Description = ListKp[i].Description;
catalogProducts[i].Specification = ListKp[i].Specification;
//...
}
_context.CatalogProducts.UpdateRange(catalogProducts);
_context.SaveChanges();
}
transaction.Commit();
}
if (numP > 0)
{
TempData["Sucessmsg"] = "No conflicts. " + numP + " product details saved.";
(from p in _context.K360MappingMasters
where p.ApiUrl == baseurl
select p).ToList()
.ForEach(x => x.InsertStatusFlag = true);
_context.SaveChanges();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
TempData["Exceptionmsg"] = ex;
return RedirectToAction("Index"); ;
throw;
}
return RedirectToAction("Index");
}
I have accepted your answer. Thanks. But I have few more clarifications need for the same question
1.CatalogProduct table has Auto increment primary key Id field only. I am inserting data from JSON URL. The unique field should be the product name. How to check whether the product name already exists in the table before adding/updating records.
2.If I need to add another JSON URL data, how do I differentiate the two URL product details?
There is no entities in db being tracked when doing Update, so it will directly add them.
You can try the below codes.
else
{
var catalogProducts= (from gcM in _context.CatalogProducts select gcM).ToList();
for (int i = 0; i < catalogProducts.Count; i++)
{
catalogProducts[i].Name = ListKp[i].Name;
catalogProducts[i].Price = ListKp[i].Price;
//...
}
_context.CatalogProducts.UpdateRange(catalogProducts);
numP = _context.SaveChanges();
}
Update:
using (var transaction = _context.Database.BeginTransaction())
{
var catalogProducts = _context.CatalogProducts.ToList();
foreach(var kp in ListKp)
{
if(!catalogProducts.Any(x => x.Name == kp.Name)){
_context.CatalogProducts.Add(kp);
_context.SaveChanges();
}
else
{
//Use AutoMapper automatically do the mapping
var config = new MapperConfiguration(cfg => cfg.CreateMap<CatalogProduct, CatalogProduct>().ForMember(c => c.Id, opt => opt.Ignore()));
var oldone = catalogProducts.FirstOrDefault(c => c.Name == kp.Name);
var mapper = config.CreateMapper();
oldone = mapper.Map<CatalogProduct,CatalogProduct>(kp, oldone);
_context.CatalogProducts.Update(oldone);
_context.SaveChanges();
}
}
transaction.Commit();
}

System.Linq.Queryable.Except is not supported in Entity Framework Core

Please note this error message :
System.NotSupportedException: 'Could not parse expression
'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
This overload of the method 'System.Linq.Queryable.Except' is
currently not supported.'
Is supported in newer versions of ef core?
my code :
var tuple = SearchBrand(searchTerm);
var result = GetExceptionsBrand(tuple.Item1, categoryId);
return Json(new
{
iTotalDisplayRecords = tuple.Item2,
iDisplayedBrand = result
.Skip(page * 10)
.Take(10)
.ToList(),
});
public async Task<Tuple<IQueryable<BrandDto>, int, int>>SearchBrand(string searchTerm)
{
var result = _context.Brands
.Where(c => c.IsDeleted == displayIsDeleted)
.WhereDynamic(searchTerm)
return new Tuple<IQueryable<BrandDto>, int, int>(result,
filteredResultsCount, totalResultsCount);
}
public IQueryable<BrandDto> GetExceptionsBrand(IEnumerable<BrandDto> filteredBrand, int categoryId)
{
var query = _context.CategoriesBrands.Where(x => x.CategoryId == categoryId);
var selectedList = new List<BrandDto>();
foreach (var item in query)
{
var cb = new BrandDto()
{
BrandDto_BrandId = item.BrandId
};
selectedList.Add(cb);
}
IQueryable<BrandDto> ExcpetList = filteredBrand.AsQueryable().Except(selectedList, new ComparerBrand());
return ExcpetList;
}

opcua session was closed by client

I have written the attached OpcUaConnector class for opc-ua connection related activities.
But it is not handling session. For example:
In opc ua configuration disabled the endpoint
In kepserver configuration did runtime > reinitializing
The windows service is throwing:
Source : system.Reactive.Core
InnerException : The session was closed by client
and stopping the windows service, as this error goes unhandled.
Can some one suggest how to handle session in opc-ua?
public class OpcUaConnector
{
private static SimplerAES simplerAES = new SimplerAES();
private DataContainer dataCointainer = null;
private UaTcpSessionChannel channel;
private string opcServerName = string.Empty;
private string opcUserId = string.Empty;
private string opcPassword = string.Empty;
private static ILog LogOpcStore;
private static System.IDisposable token;
private static uint id;
public OpcConnector(ILog Log)
{
IntializeLogOpcStore(Log);
}
private static void IntializeLogOpcStore(ILog Log)
{
LogOpcStore = Log;
}
public async Task OpenOpcConnection()
{
try
{
if ((!string.IsNullOrEmpty(this.opcServerName) & (this.opcServerName != AppMain.MyAppSettings.OpcServer)) ||
(!string.IsNullOrEmpty(this.opcUserId) & (this.opcUserId != AppMain.MyAppSettings.OpcUserId)) ||
(!string.IsNullOrEmpty(this.opcPassword) & (this.opcPassword != AppMain.MyAppSettings.OpcPassword)))
{
await channel.CloseAsync();
this.opcServerName = AppMain.MyAppSettings.OpcServer;
this.opcUserId = AppMain.MyAppSettings.OpcUserId;
this.opcPassword = AppMain.MyAppSettings.OpcPassword;
}
if (channel==null || (channel != null && (channel.State == CommunicationState.Closed || channel.State == CommunicationState.Faulted)))
{
var appDescription = new ApplicationDescription()
{
ApplicationName = "MyAppName",
ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:MyAppName",
ApplicationType = ApplicationType.Client,
};
//application data won't be deleted when uninstall
var certificateStore = new DirectoryStore(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), MyAppName", "pki"),
true, true
);
//if the Ethernet cable unplugs or the Wifi drops out,
//you have some timeouts that can keep the session open for a while.
//There is a SessionTimeout (default of 2 min).
this.channel = new UaTcpSessionChannel(
appDescription,
certificateStore,
SignInOpc,
AppMain.MyAppSettings.OpcServer,
null,
options: new UaTcpSessionChannelOptions { SessionTimeout = 120000 });
await channel.OpenAsync();
//LogOpcStore.Info(String.Format("Opc connection sucessful"));
}
this.opcServerName = AppMain.MyAppSettings.OpcServer;
this.opcUserId = AppMain.MyAppSettings.OpcUserId;
this.opcPassword = AppMain.MyAppSettings.OpcPassword;
}
catch (Exception ex)
{
ServiceException serviceException = new ServiceException(ex.HResult + " " + ex.Message, "C052");
throw serviceException;
}
}
private static async Task RecursivelyFindNode(UaTcpSessionChannel channel, NodeId nodeid)
{
BrowseRequest browseRequest = new BrowseRequest
{
NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = nodeid, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } },
};
BrowseResponse browseResponse = await channel.BrowseAsync(browseRequest);
foreach (var rd1 in browseResponse.Results[0].References ?? new ReferenceDescription[0])
{
uint chid = AppMain.MyTagDatabase.GetClientHandleByTag(rd1.DisplayName.ToString());
if (chid > 0)
{
AppMain.MyTagDatabase.UpdateNodeByClientHandle(chid, rd1.NodeId.ToString());
}
await RecursivelyFindNode(channel, ExpandedNodeId.ToNodeId(rd1.NodeId, channel.NamespaceUris));
}
}
public async Task CreateSubscription(DataContainer dc)
{
double curReadingValue;
try
{
dataCointainer = dc;
await RecursivelyFindNode(channel, NodeId.Parse(ObjectIds.RootFolder));
if (AppMain.MyTagDatabase.GetCntTagsNotInOpcServer() == AppMain.MyTagDatabase.GetTagCount())
{
//no need to create subscription
return;
}
//subscription timeout that is the product of PublishingInterval * LifetimeCount:
var subscriptionRequest = new CreateSubscriptionRequest
{
RequestedPublishingInterval = 1000f,
RequestedMaxKeepAliveCount = 30,
RequestedLifetimeCount = 30 * 3,
PublishingEnabled = true,
};
var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest);
id = subscriptionResponse.SubscriptionId;
var itemsToCreate = new MonitoredItemCreateRequest[AppMain.MyTagDatabase.GetTagHavingNodeCount()];
int i = 0;
foreach (var item in AppMain.MyTagDatabase.GetMyTagDatabase())
{
var itemKey = item.Key;
var itemValue = item.Value;
itemsToCreate[i] = new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse(itemValue.NodeId), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = itemKey, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } };
i++;
}
var itemsRequest = new CreateMonitoredItemsRequest
{
SubscriptionId = id,
ItemsToCreate = itemsToCreate,
};
var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest);
token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr =>
{
// loop thru all the data change notifications
// receiving data change notifications here
var dcns = pr.NotificationMessage.NotificationData.OfType<DataChangeNotification>();
foreach (var dcn in dcns)
{
foreach (var min in dcn.MonitoredItems)
{
MyTag MyTag = new MyTag();
bool hasValue = AppMain.MyTagDatabase.GetMyTag(min.ClientHandle, out MyTag);
if (hasValue)
{
if (double.TryParse(min.Value.Value.ToString(), out curReadingValue))
{
//LogOpcStore.Info(String.Format("ClientHandle : {0} TagName : {1} SourceTimestamp : {2} ServerTimeStamp : {3} curReadingValue : {4}", min.ClientHandle, MyTag.TagName, min.Value.SourceTimestamp, min.Value.ServerTimestamp, curReadingValue));
AddDataPointToContainer(1, MyTag.TagName, min.Value.SourceTimestamp, curReadingValue);
}
}
}
}
});
}
catch (Exception ex)
{
//If the interruption lasts longer than these timeouts then the SessionChannel and Subscriptions will need to be recreated.
channel = null;
FatalServiceException fatalserviceException = new FatalServiceException(ex.Message, "C052");
throw fatalserviceException;
}
}
public async Task DeleteSubscription()
{
try
{
var request = new DeleteSubscriptionsRequest
{
SubscriptionIds = new uint[] { id }
};
await channel.DeleteSubscriptionsAsync(request);
token.Dispose();
}
catch (Exception ex)
{
ServiceException serviceException = new ServiceException(ex.Message, "C052");
throw serviceException;
}
}
private static async Task<IUserIdentity> SignInOpc(EndpointDescription endpoint)
{
IUserIdentity userIdentity = null;
if (endpoint.UserIdentityTokens.Any(p => p.TokenType == UserTokenType.Anonymous))
{
userIdentity = new AnonymousIdentity();
}
else if (endpoint.UserIdentityTokens.Any(p => p.TokenType == UserTokenType.UserName))
{
var userName = AppMain.MyAppSettings.OpcUserId;
var password = simplerAES.Decrypt(AppMain.MyAppSettings.OpcPassword);
userIdentity = new UserNameIdentity(userName, password);
}
return userIdentity;
}
private void AddDataPointToContainer(int dataType, string source, DateTime SourceTimestampUTC, double value)
{
ConditionValue conditionValue = new ConditionValue();
long timestamp = AppMain.ServerSyncTimeStore.ConvertDateTimeToTimeStampUTC(SourceTimestampUTC);
conditionValue.dataType = dataType;
conditionValue.source = source;
conditionValue.timestamp = timestamp;
conditionValue.SourceTimestampUTC = SourceTimestampUTC;
conditionValue.LocalTime = SourceTimestampUTC.ToLocalTime();
conditionValue.value = value;
//LogOpcStore.Info(String.Format("TagName : {0} SourceTimestampUTC : {1} timestamp : {2} LocalTime : {3} curReadingValue : {4}", source, SourceTimestampUTC, timestamp, SourceTimestampUTC.ToLocalTime(), value));
dataCointainer.AddDataPoint(conditionValue);
}
}
I see you are using the project https://github.com/convertersystems/opc-ua-client.
When a server closes the session and socket (as happens when you reinitialize Kepware) the client receives immediate notification that causes the client channel to fault. A faulted channel cannot be reopened, it should be aborted and a new channel should be created.
I made this standalone test, to show that you may have to catch an exception and recreate the channel and subscription. The point of this test is to subscribe to the CurrentTime node and collect 60 datachanges. The test should last a minute. If you re-init the Kepware server in the middle of the test, the code catches the exception and recreates the channel and subscription.
[TestMethod]
public async Task OpcConnectorTest()
{
var count = 0;
UaTcpSessionChannel channel = null;
while (count < 60)
{
try
{
channel = new UaTcpSessionChannel(
this.localDescription,
this.certificateStore,
new AnonymousIdentity(),
EndpointUrl,
SecurityPolicyUris.None,
loggerFactory: this.loggerFactory);
await channel.OpenAsync();
// create the keep alive subscription.
var subscriptionRequest = new CreateSubscriptionRequest
{
RequestedPublishingInterval = 1000f,
RequestedMaxKeepAliveCount = 30,
RequestedLifetimeCount = 30 * 3,
PublishingEnabled = true,
};
var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false);
var id = subscriptionResponse.SubscriptionId;
var token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr =>
{
// loop thru all the data change notifications
var dcns = pr.NotificationMessage.NotificationData.OfType<DataChangeNotification>();
foreach (var dcn in dcns)
{
foreach (var min in dcn.MonitoredItems)
{
Console.WriteLine($"sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}");
count++;
}
}
});
var itemsRequest = new CreateMonitoredItemsRequest
{
SubscriptionId = id,
ItemsToCreate = new MonitoredItemCreateRequest[]
{
new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }
},
};
var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest);
while (channel.State == CommunicationState.Opened && count < 60)
{
await Task.Delay(1000);
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.GetType()}. {ex.Message}");
}
}
if (channel != null)
{
Console.WriteLine($"Closing session '{channel.SessionId}'.");
await channel.CloseAsync();
}
}
I know this is an old post, but I stumbled upon this problem as well. For those interested:
The problem is related to the subscription(s).
When the following code is run:
token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr =>
{
// loop thru all the data change notifications
// receiving data change notifications here
var dcns = pr.NotificationMessage.NotificationData.OfType<DataChangeNotification>();
foreach (var dcn in dcns)
{
foreach (var min in dcn.MonitoredItems)
{
MyTag MyTag = new MyTag();
bool hasValue = AppMain.MyTagDatabase.GetMyTag(min.ClientHandle, out MyTag);
if (hasValue)
{
if (double.TryParse(min.Value.Value.ToString(), out curReadingValue))
{
//LogOpcStore.Info(String.Format("ClientHandle : {0} TagName : {1} SourceTimestamp : {2} ServerTimeStamp : {3} curReadingValue : {4}", min.ClientHandle, MyTag.TagName, min.Value.SourceTimestamp, min.Value.ServerTimestamp, curReadingValue));
AddDataPointToContainer(1, MyTag.TagName, min.Value.SourceTimestamp, curReadingValue);
}
}
}
}
});
Observable.subscribe() takes multiple arguments. You should include what to do in case of an error. For example:
token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(
pr => { code to run normally... },
ex => { Log.Info(ex.Message); },
() => { }
);
See http://reactivex.io/documentation/operators/subscribe.html for more information.

Moled Dataset using Pex and Moles

I want to test below method.I am returning dataset and checking table collection.
public string FetchAllDetails(string useCase, string strMainFlow)
{
var strError = new StringBuilder();
DataSet ds = _dal.Fetchdetails(useCase, strMainFlow, useCaseId, useCaseName);
DataTable dt = new DataTable();
dt = ds.Tables[0];
if (dt.Rows.Count > 0)
{
BindUsecaseId(strError, useCaseName);
foreach (var row in ds.Tables[0].AsEnumerable())
BindError(strError, GetOriginalFieldName(row[0].ToString()));
}
return strError.ToString();
}
I wrote below unit test using Pex.
[PexMethod]
public string FetchAllDetailsTest(string useCase, string strMainFlow)
{
SIUploadtoolDAL dal = new SIUploadtoolDAL();
UploadtoolBL target = new UploadtoolBL(dal);
MDataTableCollection dt2 = new MDataTableCollection();
dt2.Add = () =>
{
MDataTable dt1 = new MDataTable();
dt1.ColumnsGet = () =>
{
MDataColumnCollection dcCollection = new MDataColumnCollection();
dcCollection.Add = () =>
{
MDataColumn dc = new MDataColumn();
dc.ColumnNameGet = () =>
{
return "string";
};
dc.DataTypeGet = () =>
{
return typeof(string);
};
return dc;
};
return dcCollection;
};
return dt1;
};
dal.FetchdetailsStringStringInt32StringSqlTransaction = (useCaselocal, strMainFlowlocal, useCaseIdlocal, useCaseNamelocal) =>
{
MDataSet ds = new MDataSet();
ds.TablesGet = () =>
{
MDataTableCollection dt = new MDataTableCollection();
dt.Add = () =>
{
MDataTable dt1 = new MDataTable();
dt1.ColumnsGet = () =>
{
MDataColumnCollection dcCollection = new MDataColumnCollection();
dcCollection.Add = () =>
{
MDataColumn dc = new MDataColumn();
dc.ColumnNameGet = () =>
{
return "string";
};
dc.DataTypeGet = () =>
{
return typeof(string);
};
return dc;
};
return dcCollection;
};
return dt1;
};
return dt;
};
return ds;
};
return target.FetchAllDetails(useCase, strMainFlow, useCaseId, useCaseName);
}
Now I am getting MoledNotImplemented for DataTablecollection error.
How I can moled dataset tabele collection?