trouble with getting data from web api and Entity Framework - c#

I wrote database on Entity Framework Code First and i use it in my Web Api.
If i have more than 400 records in my table ,i can`t get any records, but if i have less than 400 record everything works ok . This is my code for getting records :
public IEnumerable<Contact> Get(int pageSize, int pageIndex)
{
return db.Set<Contact>().OrderBy(e => e.Id).Skip(pageSize * pageIndex).Take(pageSize).AsParallel<Contact>().AsOrdered();
}
Another method for getting 1 record doesnt work too.
public Contact Get(int id) { return db.Set<Contact>().Find(id); }
And i notice with adding new records times for response increments.
When i have 100 record time for response is 4 second,if i have 200 second 10 seconds.
Can you explain what i am doing wrong ?
EDIT: code from controller
private ICompanyService companyService;
public CompaniesController(ICompanyService companyService)
{
this.companyService = companyService;
}
//// GET api/companies
public IHttpActionResult Get([FromUri]int SizePage=100, [FromUri]int Page=1)
{
return Ok(companyService.Get(SizePage, Page));
}
//// GET api/companies/5
public IHttpActionResult Get([FromUri]int id)
{
return Ok(companyService.Get(id));
}

Related

Angular - Send a request with multiple models to API

I'm new in Angular, and I'm currently into a big project where many people work, so the project is based on Angular for the front end and C# for the back end.
So, the project has some services that call the backend service:
Front:
public editProfileClient(profileClient) {
return this.http
.post(this.url + '/editProfileClient', profileClient)
.pipe(map((result: ProfileClientModel) => result));
}
Back:
public async Task<ActionResult> EditProfileClient(ProfileClient profileClient)
{
//irrelevant code here
return Ok(model);
}
This is working well, but now I want to send a new model called Salary to that request, so I changed the back as:
public async Task<ActionResult> EditProfileClient(ProfileClient profileClient, Salary salary)
but I have no idea how I can send it on the front, so I receive it, but I cannot call it:
public editProfileClient(profileClient, salary) {
return this.http
.post(this.url + '/editProfileClient', profileClient, salary)
.pipe(map((result: ProfileClientModel) => result));
}
If I try to do that, the method returns an error:
Argument of type 'OperatorFunction<ProfileClientModel,
ProfileClientModel>' is not assignable to parameter of type
'OperatorFunction<ArrayBuffer, ProfileClientModel>'.
How can I achieve that?
For the API part, combine both parameters into a single object as below:
public async Task<ActionResult> EditProfileClient(EditProfileClientInputModel input)
public class EditProfileClientInputModel
{
public ProfileClient ProfileClient { get; set; }
public Salary Salary { get; set; }
}
For the front-end part:
2.1. Combine both profileClient and salary parameters into a single object and pass it.
2.2. As your API returns the response of ProfileClientModel type, you should also specify the generic type: post<T>()
public editProfileClient(profileClient, salary) {
let input = {
profileClient: profileClient,
salary: salary
};
return this.http
.post<ProfileClientModel>(this.url + '/editProfileClient', input);
}
Update
.pipe(map((result: ProfileClientModel) => result))
As per Eliseo's feedback, the pipe() should be removed as map() is used to transform the data, while you try to transform the value into the same value, which is unnecessary.

Select Distinct Records From Sql Server With Entity Framework Using Repository Pattern In .Net Core 5

I am using the repository pattern with the .Net Core Web Application that communicates with .Net Core Web API Controller Methods to get records from SqlServer.
On the Web API Controller method, I am calling a method in the repository which must return a list of distinct messages based on a specific field in the Sql Server database like PhoneNumberTo. However, there seem to be some casting errors when I am returning the list back to the API method. Here is my Web API Controller method which calls the repository:
[HttpGet]
[Route("GetUniqueMessages")]
public IActionResult GetUniqueMessages()
{
var messages = _unitOfWork.MessagesViewModel.GetDistinctMessages();
return new JsonResult(messages);
}
And here is my repository method which must return the list of distinct messages:
public IEnumerable<Message> GetDistinctMessages()
{
List<Message> result = _context.Messages.Select(m => m.PhoneNumberTo).Distinct().ToList();
return result;
}
Here is a screenshot of the error message I am getting on the repository method.
Update:
Here is my Message class:
Any expert suggestion will highly be appreciated.
you have two choices.
If you need to get a list of phone numbers only
public IEnumerable<string> GetDistinctMessages()
{
return _context.Messages.Select(m => m.PhoneNumberTo).Distinct().ToArray();
}
If you need a list of messages, you can't have have all distinct fields, it will be the same like this
public IEnumerable<Message> GetDistinctMessages()
{
return _context.Messages.Distinct().ToArray();
}
I offer you to get MessageTo MessageFrom and MessageText and see the difference
public IEnumerable<Message> GetDistinctMessages()
{
return _context.Messages
.GroupBy(p => new {p.MessageTo, p.MessageFrom} )
.Select(g => new Message
{
MessageTo = g.Key.MessageTo,
MessageFrom = g.Key.MessageFrom,
MessageText= g.MessageText
}).ToArray();
You can play with this query and add as many fields as you need
you can still keep an existing action, but I recomend this
[HttpGet]
[Route("GetUniqueMessages")]
public IActionResult GetUniqueMessages()
{
var messages = _unitOfWork.MessagesViewModel.GetDistinctMessages();
return Ok(messages);
}

.Net Core API to count item from database

I'm trying to count Order from Database with API but it doesn't seem to work.
There's a message from Swagger that said "Failed to load API definition. Fetch error undefined swagger/v1/swagger.json"
This is in OrderController:
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))]
public async Task<ActionResult<int>> CountOrders()
{
int result = await _orderService.CountOrders();
return Ok(result);
}
This is in OrderService:
public async Task<int> CountOrders()
{
return _orderRepository.CountOrder();
}
This is in OrderRepository:
public int CountOrder()
{
IQueryable<DataProvider.Entities.Order> orderList;
orderList = GetAll();
return orderList.Count();
}
I'm new to this so please point out if there's anything makes you feel uncomfortable. Thanks.
I solved it. I was kind of stupid and didn't realise I haven't change the route, so it got duplicated.
It works after adding [Route("count")]

UnitTest EF Core InMemoryDatabase - row ID mismatch in basic CRUD operations

I have a Visual Studio 2017 .NET Core 2.0 project with EF Core as the ORM for talking to the database.
I am trying to use XUnit to do a simple test of the DBContext that was created.
But have come across this problem that occurs only when selecting RunAll in which it occurs every time. But if I do a single test or add all tests to a playlist and run all it doesn't reproduce and the test passes.
Now the problem is in the TestGet() method below is that when I do a service.Create (dbcontext.add) it returns the ID of 1 every time.
But when I then call the data for ID 1 using service.Get(id) it returns null, and if I do a service.GetAll() it returns a single item that actually has an ID of 2.
How could the service be returning an ID of 1 even though the inMemoryDB actually created it with the ID 2 and that it only occurs when doing a RunAll test.
All code required should be below. Please note its been redacted and pasted from multiple files.
public class TestClass
{
[Fact]
public async void TestGet()
{
using (var context = new CoreContext(CoreInMemoryDbContextOptions.Get()))
{
var _testService = new TestService(context);
var newTest = new Test
{
Name = "Test",
};
var itemId = await _testService.Create(newTest); //returns ID 1
var items = await _testService.GetAll(); //returns single item with ID 2
var item = await _testService.Get(itemId); //NullException
Assert.Equal("Test", item.Name);
}
}
}
public class TestService
{
private CoreContext _context;
public TestService(CoreContext context)
{
_context = context;
}
public async Task<Data.Test> Get(int id)
{
return await _context.Tests.Where(x => x.TestId == id).SingleOrDefaultAsync();
}
public async Task<int> Create(Test component)
{
component.TestId = 0;
_context.Tests.Add(component);
return await _context.SaveChangesAsync();
}
}
public class CoreInMemoryDbContextOptions
{
public static DbContextOptions<CoreContext> Get()
{
DbContextOptions<CoreContext> options;
var builder = new DbContextOptionsBuilder<CoreContext>();
builder.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString());
options = builder.Options;
CoreContext coreContext = new CoreContext(options);
coreContext.Database.EnsureDeleted();
coreContext.Database.EnsureCreated();
return options;
}
}
Your understanding of the return value of SaveChangesAsync is flawed. You're assuming in your test that it returns the id. That's wrong. It returns the count of successful operations, which because you're saving a single entity, is 1. It is always 1. If you want the id, you need to get it from your PK property after the save. EF will backfill that property with the id that was created, but it doesn't return the id directly.

on POST back wont create new record

Using MVC Orchard services file to allow the user to enter a new record in the 'HoursWorkedToday' table, allowing the user to enter how many hours they have worked that day.
//HoursWorkedService
public class HoursWorkedService : IHoursWorkedService
{
private IRepository<HoursWorkedPerDay> _repository = null;
public HoursWorkedService(IRepository<HoursWorkedPerDay> Repository)
{
_repository = Repository;
}
public Models.HoursWorkedPerDay Create(HoursWorkedPerDay newRecordForHoursWorked)
{
_repository.Create(newRecordForHoursWorked);
return newRecordForHoursWorked;
}
//IHoursWorkedService
public interface IHoursWorkedService : IDependency
{
HoursWorkedPerDay Create(HoursWorkedPerDay newRecordForHoursWorked);
}
//controller
[HttpPost, ActionName("HoursWorkedPerDay")]
public ActionResult HoursWorkedPerDayPOST(int userId, int hours)
{
DateTime TodaysDate = DateTime.UtcNow;
HoursWorkedPerDay HoursPerDay = new HoursWorkedPerDay();
HoursPerDay.Date = TodaysDate;
HoursPerDay.WorkerRecord_Id = userId;
HoursPerDay.HoursWorked = hours;
_hoursWorked.Create(HoursPerDay);
_notifier.Add(NotifyType.Information, T("Thank you, Hours Added."));
return RedirectToAction("Index");
}
but after the post i get the 'website can not display'
LOGS show:
Cannot insert the value NULL into column 'Id', table 'Orchard.Timekeeper.dbo.Timekeeper_HoursWorkedPerDay'; column does not allow nulls. INSERT fails
In my migration file i have 'id' set to .ContentPartRecord(), which i assumed created the next record automatically when the service was used
Do not use ContentPartRecord on something that is not a content part record. Instead, add the Id column yourself as identity so that it gets auto-incremented.
If it is meant as a content part record, never use it without a content item. In particular, never use the repository directly on part records, and go through the content manager instead.

Categories