How to implement async function? - asp.net

I would like that my function fulfilled asynchronously. I still learn to write the asynchronous code and would like to ask your help. How does such funtion have to be written?
class CustomerController : Controller
{
private ICustomerRepository _customerRepository;
public CustomerController(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
[HttpGet]
public IActionResult Index()
{
IEnumerable<CustomerViewModel> customers =
_customerRepository.GetAllCustomers().Select(s => new CustomerViewModel
{
CustomerId = s.CustomerId,
Name = s.Name,
Adress = s.Adress
});
return View("Index", customers);
}
}
Interface:
public interface ICustomerRepository
{
IEnumerable<Customer> GetAllCustomers();
}
public class CustomerRepository : ICustomerRepository
{
private StoreDBContext _db;
public CustomerRepository(StoreDBContext db)
{
_db = db;
}
public IEnumerable<Customer> GetAllCustomers()
{
return _db.Customers;
}
}

[HttpGet]
public async Task<IActionResult> Index()
{
IEnumerable<CustomerViewModel> customers =
_customerRepository.GetAllCustomers().Select(s => new CustomerViewModel
{
CustomerId = s.CustomerId,
Name = s.Name,
Adress = s.Adress
});
return View("Index", customers);
}

Related

DbContext in Service triggered by Hangfire

I have a .NET 6 Razor Pages app that triggers background tasks and then informs the user of their status via SignalR.
I'm trying to use Database1 context in the PerformBackgroundJob method, but it's disposed. What technique should I use to inject Database1 context in PerformBackgroundJob, or how else can I get this to work?
namespace Toolkat.Pages
{
public class ProcessModel : PageModel
{
private readonly Database1Context _context;
private readonly ToolkatContext _tkcontext;
private IConfiguration configuration;
private readonly IQueue _queue;
private readonly IHubContext<JobHub> _hubContext;
static ServerConnection conn;
static Server server;
static Job job;
public ProcessModel(
Database1Context context,
ToolkatContext tkcontext,
IConfiguration _configuration,
IQueue queue,
IHubContext<JobHub> hubContext)
{
_context = context;
_tkcontext = tkcontext;
configuration = _configuration;
_queue = queue;
_hubContext = hubContext;
}
public IList<CustomFileImport> CustomFileImport { get; set; } = default!;
[BindProperty]
public CustomFileImport CustomFileImportNumberTwo { get; set; } = default!;
public async Task OnGetAsync()
{
if (_context.CustomFileImports != null)
{
CustomFileImport = await _context.CustomFileImports
.Include(c => c.FileImportType)
.Include(c => c.FileImportStatus)
.Where(i => i.FileImportStatusId.Equals(1))
.ToListAsync();
}
}
public async Task<IActionResult> OnPostAsync(int[] fileImportId)
{
//Generate GUID
Guid jobId = Guid.NewGuid();
//Update FileImportItems with GUID
foreach (var id in fileImportId)
{
if (/*id == null ||*/ _context.CustomFileImports == null)
{
return NotFound();
}
var customfileimport = await _context.CustomFileImports.FirstOrDefaultAsync(m => m.FileImportId == id);
if (customfileimport == null)
{
return NotFound();
}
customfileimport.ProcessId = jobId;
await _context.SaveChangesAsync();
}
_queue.QueueAsyncTask(() => PerformBackgroundJob(jobId));
return RedirectToPage("./Result", new { jobId });
}
private async Task PerformBackgroundJob(Guid jobId /*CancellationToken cancellationToken*/)
{
await _hubContext.Clients.Group(jobId.ToString()).SendAsync("progress", "PerformBackgroundJob Started");
/*
var customFileImports = await _context.CustomFileImports
.Include(c => c.FileImportType)
.Where(i => i.ProcessId.Equals(jobId))
.ToListAsync();
*/
Debug.WriteLine("ProviderName:" + _context.Database.ProviderName);
/*
foreach (var f in customFileImports)
{
await _hubContext.Clients.Group(jobId.ToString()).SendAsync("progress", WebUtility.HtmlEncode(f.FileName));
}
*/
}
}
}
I had to combine lessons from lots of articles to figure this out. Hangfire has a nice way of approaching this.
Replace
_queue.QueueAsyncTask(() => PerformBackgroundJob(jobId));
With
BackgroundJob.Enqueue<ProcessFilesService>(x => x.DoWork());
Passing dependencies
and create this class
public class ProcessFilesService
{
IServiceProvider _serviceProvider;
public ProcessFilesService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void DoWork()
{
using var scope = _serviceProvider.CreateScope();
var ctx = scope.ServiceProvider.GetRequiredService<MyDatabaseContext>();
using var hubScope = _serviceProvider.CreateScope();
var _hubContext = hubScope.ServiceProvider.GetRequiredService<JobHub>();
Debug.WriteLine(ctx.Database.ProviderName);
}
}
Hmm...I didn't need to register it as a service in program.cs and it appears to still be working. Will have to learn more about that.

Edit action is not doing anything on automapper

I´m using Visual Studio 2019, .net core 3.1 and automapper. My Edit action dont edit the record. I´ve seen tutorials but all are just of one action and I need to do a crud. Taking as example a usual edit action I´ve made this:
public class CustomerCountriesController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IMapper _mapper;
public CustomerCountriesController(ApplicationDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
// GET: CustomerCountries
public async Task<IActionResult> Index()
{
//CustomerCountries customerCountry = new CustomerCountries();
var customerCountry = await _context.CustomerCountries.ToListAsync();
List<CustomerCountriesDto> countries = _mapper.Map<List<CustomerCountries>,
List<CustomerCountriesDto>>(await _context.CustomerCountries.ToListAsync());
return View(countries);
}
public async Task<IActionResult> Edit(string id)
{
if (id == null)
{
return NotFound();
}
var customerCountries = await _context.CustomerCountries.FindAsync(id);
var model = _mapper.Map<CustomerCountries, CustomerCountriesDto>(customerCountries);
if (customerCountries == null)
{
return NotFound();
}
return View(model);
//return View(customerCountries);
}
// POST: CustomerCountries/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
//public async Task<IActionResult> Edit(string id, [Bind("CustomerCountry")] CustomerCountries customerCountries)
public async Task<IActionResult> Edit(string customerCountry, CustomerCountriesDto customerCountriesDto)
{
if (customerCountry != customerCountriesDto.CustomerCountry)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
var CustomerCountries = _mapper.Map<CustomerCountriesDto, CustomerCountries>(customerCountriesDto);
_context.Update(CustomerCountries);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CustomerCountriesExists(customerCountriesDto.CustomerCountry))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(customerCountriesDto);
}
public class AutoMapping : Profile
{
public AutoMapping()
{
CreateMap<CustomerCountries, CustomerCountriesDto>();
CreateMap<CustomerCountriesDto, CustomerCountries>();
}
}
public class CustomerCountries
{
[StringLength(50, ErrorMessage = "Longitud máxima para el país: 50")]
public string CustomerCountry { get; set; }
public ICollection<CustomerRegions> CustomerRegions { get; set; }
}
public class CustomerCountriesDto
{
public string CustomerCountry { get; set; }
}
On startup
services.AddAutoMapper(typeof(Startup));
The id of the table is CustomerCounty
Can you tell me the correct way?
I´ve found the solution thanks to an experienced developer that lead me through the issue and corrected my code from time to time (That is acctually really helping guys). Turns out that I was using a field as a PK: CustomerCountry... I wasn´t using and Id, when I changed the model, the update happened
var CustomerCountries = _mapper.Map<CustomerCountriesDto, CustomerCountries>(customerCountriesDto);
var country = _context.CustomerCountries.FirstOrDefault(c => c.Id == CustomerCountries.Id);
country.CustomerCountry = customerCountriesDto.CustomerCountry;
_context.Update(country);
await _context.SaveChangesAsync();

unit text mock dbContext

I try to do a unitary test on a repository that returns a Ienumerable. But I have the next mistake:
System.AggregateException : One or more errors occurred. (The source IQueryable doesn't implement IAsyncEnumerable<myNamespace.DTO.UserDTO>. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.)
---- System.InvalidOperationException : The source IQueryable doesn't implement IAsyncEnumerable<myNamespace.DTO.UserDTO>. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.
This my unit test :
//Arrange
var mockSet = Substitute.For<DbSet<User>, IQueryable<User>, IDbAsyncEnumerable<User>>();
((IDbAsyncEnumerable<User>)mockSet).GetAsyncEnumerator()
.Returns(new TestDbAsyncEnumerator<User>(GetUserList().AsQueryable().GetEnumerator()));
((IQueryable<User>)mockSet).Provider.Returns(new TestDbAsyncQueryProvider<User>(GetUserList().AsQueryable().Provider));
((IQueryable<User>)mockSet).Expression.Returns(GetUserList().AsQueryable().Expression);
((IQueryable<User>)mockSet).ElementType.Returns(GetUserList().AsQueryable().ElementType);
((IQueryable<User>)mockSet).GetEnumerator().Returns(GetUserList().AsQueryable().GetEnumerator());
var mockContext = Substitute.For<IMyContext>();
mockContext.Users.Returns(mockSet);
//Act
CancellationToken cancellationToken = new CancellationToken();
UserRepository userRepository = new UserRepository(mockContext);
var users = userRepository.GetListAsync(cancellationToken).Result;
//Assert
Assert.NotNull(users);
My repo I want to test :
public async Task<IEnumerable<UserDto>> GetListAsync(CancellationToken cancellationToken)
{
return await _myContext.Users.Select(u => new UserDto
{
Id = u.Id,
FistName = u.FistName ,
LastName = u.LastName
}).ToListAsync(cancellationToken);
}
What is the problem ?
As covered in the OP comments the doco you're referring to is for EF, not EFCore. You need to implement a different set of interfaces.
The usual advice is to avoid mocking the DbContext however in this case you probably need to as the async operations aren't supported by the in-memory provider. I'm not sure if SQLite supports them. EntityFrameworkCore.Testing should handle this case (disclaimer, I am the author), but you'd need to use your context implementation rather than an interface.
The most common way to get this working is to create implementations of the async interfaces, in the same manner as the EF doco but for EFCore. You'll find most EFCore mocking libraries will do it this way:
public class TestAsyncEnumerable<T> : IAsyncEnumerable<T>, IOrderedQueryable<T>
{
private readonly IEnumerable<T> _enumerable;
private readonly IQueryable<T> _queryable;
public TestAsyncEnumerable(IEnumerable<T> enumerable)
{
_enumerable = enumerable;
_queryable = _enumerable.AsQueryable();
ElementType = _queryable.ElementType;
Expression = _queryable.Expression;
Provider = new TestAsyncQueryProvider<T>(_queryable);
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
return new TestAsyncEnumerator<T>(_queryable);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
public Type ElementType { get; }
public Expression Expression { get; }
public IQueryProvider Provider { get; }
}
public class TestAsyncEnumerator<T> : IAsyncEnumerator<T>
{
private readonly IEnumerator<T> _enumerator;
public TestAsyncEnumerator(IEnumerable<T> enumerable)
{
_enumerator = enumerable.GetEnumerator();
}
public ValueTask DisposeAsync()
{
return new ValueTask();
}
public ValueTask<bool> MoveNextAsync()
{
return new ValueTask<bool>(_enumerator.MoveNext());
}
public T Current => _enumerator.Current;
}
public class TestAsyncQueryProvider<T> : IAsyncQueryProvider
{
public TestAsyncQueryProvider(IQueryable<T> source)
{
Source = source;
}
private IQueryable<T> Source { get; }
public IQueryable CreateQuery(Expression expression)
{
throw new NotImplementedException();
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestAsyncEnumerable<TElement>(Source.Provider.CreateQuery<TElement>(expression));
}
public object Execute(Expression expression)
{
throw new NotImplementedException();
}
public TResult Execute<TResult>(Expression expression)
{
throw new NotImplementedException();
}
public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = new CancellationToken())
{
throw new NotImplementedException();
}
}
This isn't a complete implementation, just what's needed to solve the OP case. The important bit is this line:
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestAsyncEnumerable<TElement>(Source.Provider.CreateQuery<TElement>(expression));
}
This is what is going to allow the projection to work with the async operation.
Working example:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using AutoFixture;
using KellermanSoftware.CompareNetObjects;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.Internal;
using NSubstitute;
using NUnit.Framework;
namespace Question62783423
{
public class Tests
{
[Test]
public void Test1()
{
var fixture = new Fixture();
var users = new TestAsyncEnumerable<User>(fixture.CreateMany<User>());
//Arrange
var mockSet = Substitute.For<DbSet<User>, IQueryable<User>, IAsyncEnumerable<User>>();
((IAsyncEnumerable<User>) mockSet).GetAsyncEnumerator().Returns(users.GetAsyncEnumerator());
((IQueryable<User>) mockSet).Provider.Returns(users.Provider);
((IQueryable<User>) mockSet).Expression.Returns(users.Expression);
((IQueryable<User>) mockSet).ElementType.Returns(users.ElementType);
((IQueryable<User>) mockSet).GetEnumerator().Returns(((IQueryable<User>) users).GetEnumerator());
var mockContext = Substitute.For<IMyContext>();
mockContext.Users.Returns(mockSet);
//Act
var cancellationToken = new CancellationToken();
var userRepository = new UserRepository(mockContext);
var result1 = userRepository.GetListAsync(cancellationToken).Result;
var result2 = userRepository.GetListAsync(cancellationToken).Result;
var comparer = new CompareLogic();
comparer.Config.IgnoreCollectionOrder = true;
comparer.Config.IgnoreObjectTypes = true;
var comparisonResult1 = comparer.Compare(users, result1);
var comparisonResult2 = comparer.Compare(users, result2);
Assert.That(comparisonResult1.Differences.Any(), Is.False);
Assert.That(comparisonResult2.Differences.Any(), Is.False);
}
}
}
public class TestAsyncEnumerable<T> : IAsyncEnumerable<T>, IOrderedQueryable<T>
{
private readonly IEnumerable<T> _enumerable;
private readonly IQueryable<T> _queryable;
public TestAsyncEnumerable(IEnumerable<T> enumerable)
{
_enumerable = enumerable;
_queryable = _enumerable.AsQueryable();
ElementType = _queryable.ElementType;
Expression = _queryable.Expression;
Provider = new TestAsyncQueryProvider<T>(_queryable);
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
return new TestAsyncEnumerator<T>(_queryable);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
public Type ElementType { get; }
public Expression Expression { get; }
public IQueryProvider Provider { get; }
}
public class TestAsyncEnumerator<T> : IAsyncEnumerator<T>
{
private readonly IEnumerator<T> _enumerator;
public TestAsyncEnumerator(IEnumerable<T> enumerable)
{
_enumerator = enumerable.GetEnumerator();
}
public ValueTask DisposeAsync()
{
return new ValueTask();
}
public ValueTask<bool> MoveNextAsync()
{
return new ValueTask<bool>(_enumerator.MoveNext());
}
public T Current => _enumerator.Current;
}
public class TestAsyncQueryProvider<T> : IAsyncQueryProvider
{
public TestAsyncQueryProvider(IQueryable<T> source)
{
Source = source;
}
private IQueryable<T> Source { get; }
public IQueryable CreateQuery(Expression expression)
{
throw new NotImplementedException();
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestAsyncEnumerable<TElement>(Source.Provider.CreateQuery<TElement>(expression));
}
public object Execute(Expression expression)
{
throw new NotImplementedException();
}
public TResult Execute<TResult>(Expression expression)
{
throw new NotImplementedException();
}
public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = new CancellationToken())
{
throw new NotImplementedException();
}
}
public class User
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class UserDto
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IMyContext
{
DbSet<User> Users { get; set; }
}
public class UserRepository
{
private readonly IMyContext _myContext;
public UserRepository(IMyContext myContext)
{
_myContext = myContext;
}
public async Task<IEnumerable<UserDto>> GetListAsync(CancellationToken cancellationToken)
{
return await _myContext.Users.Select(u => new UserDto { Id = u.Id, FirstName = u.FirstName, LastName = u.LastName }).ToListAsync(cancellationToken);
}
}

How to UNit test the API controller methods

I am really stuck and need your help.
I have a .NET Core 2.1 API and I want to create a nUnitTest project (NUnit 3.10.1) to test the controller of the API but I don't know how to call the controller's action method from the nUnitTest and really need some help.
Things I have tried:
1) Generate parameterless constructor in the controller and instantiate controller from the Test method but that doesn't work.
2) Generate a constructor in the Test class to define the db context but that also doesn't work.
Here is my API Controller:
public class PersonController : ControllerBase
{
private readonly NetCoreAPI1Context _context;
public PersonController(NetCoreAPI1Context context)
{
_context = context;
}
// POST: api/Person
[HttpPost]
public async Task<IActionResult> PostPerson([FromBody] Person person)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Persons.Add(person);
await _context.SaveChangesAsync();
return CreatedAtAction("GetPerson", new { id = person.Id }, person);
}
}
Here is NetCoreAPI1Context class
public class NetCoreAPI1Context : DbContext
{
public NetCoreAPI1Context(DbContextOptions<NetCoreAPI1Context> options)
: base(options)
{
}
public DbSet<Person> Persons { get; set; }
}
Here is Person class
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
I've verified that the PostPerson action in the controller worked.
I then add a nUnitTest project to the solution.
Here is my simple test class and method:
class PersonControllerTest
{
Person _person;
//NetCoreAPI1Context _context;
[SetUp]
public void Setup()
{
_person = new Person
{
FirstName = "David",
LastName = "Johnson",
Email = "dj#dj.com"
};
}
//public PersonControllerTest(NetCoreAPI1Context context)
//{
// _context = context;
//}
[Test]
public void PostPersonTest()
{
var person = _person; // confirm that "person" has data and ready to be used
//
// HOW To CALL THE COTROLLER METHOD PostPerson(...) HERE????
//
}
}
Here is the step about how to NUnit test:
1.In your nUnitTest project,you need to right-click Dependences and choose add reference(Web Api project):
2.WebApi Project Controller:
[Route("api/[controller]")]
[ApiController]
public class PeopleController : ControllerBase
{
private readonly WebApi2Context _context;
public PeopleController(WebApi2Context context)
{
_context = context;
}
// GET: api/People
[HttpGet]
public async Task<ActionResult<IEnumerable<Person>>> GetPerson()
{
return await _context.Person.ToListAsync();
}
// POST: api/People
[HttpPost]
public async Task<ActionResult> PostPerson(Person person)
{
_context.Person.Add(person);
await _context.SaveChangesAsync();
return CreatedAtAction("GetPerson", new { id = person.Id }, person);
}
}
3.nUnitTest project(Be sure that you have installed the package Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.SqlServer):
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NUnit.Framework;
using WebApi2.Controllers;
using WebApi2.Data;
using WebApi2.Models;
namespace NUnitTestProject1
{
class PersonControllerTest
{
public static DbContextOptions<WebApi2Context> dbContextOptions { get; }
public static string connectionString = "Server=(localdb)\\mssqllocaldb;Database=YourDatabaseName;Trusted_Connection=True;MultipleActiveResultSets=true";
Person _person;
static PersonControllerTest()
{
dbContextOptions = new DbContextOptionsBuilder<WebApi2Context>()
.UseSqlServer(connectionString)
.Options;
}
[SetUp]
public void Setup()
{
_person = new Person
{
//Id=1,If Id is not designed by using IDENTITY (1, 1),you need to add this line
FirstName = "David",
LastName = "Johnson",
Email = "dj#dj.com"
};
}
[Test]
public void Test1()
{
var context = new WebApi2Context(dbContextOptions);
PeopleController person = new PeopleController(context);
var data = person.PostPerson(_person);
var response = data.Result as CreatedAtActionResult;
var item = response.Value as Person;
Assert.AreEqual("David", item.FirstName);
Assert.AreEqual("Johnson", item.LastName);
Assert.AreEqual("dj#dj.com", item.Email);
}
}
}
4.Result:

Unit tests fails after upgrading to .net core 2

Can someone maybe explain to me what this means and why am i getting it.
System.InvalidOperationException : When called from 'VisitLambda',
rewriting a node of type 'System.Linq.Expressions.ParameterExpression'
must return a non-null value of the same type. Alternatively, override
'VisitLambda' and change it to not visit children of this type.
I am getting it from my unit tests I am running the latest .net core 2 with EF core. all my tests were fine till i upgraded then i started getting the error.
The funny thing is, is that when i run the project the line were it fails in the the tests is ok.
This is my Test
[Fact]
public async Task GetUserProfileAsync_Where_Employee_Exist_Test()
{
// Given
var user = TestPrincipal.CreatePrincipalForEmployeeUser();
using (var factory = new TestContextFactory())
using (var context = factory.CreateInMemoryDatabase<ApplicationContext>())
{
this.SetDependencies(context);
var data = EmployeeValueHelper.GetEmployeeValues();
context.AddRange(data);
context.SaveChanges();
var sut = new ProfileService(new DbContextRepository<Data.Models.Employees.Employee>(context), this.userService, this.moqEmploymentStatusService.Object);
// When
// -> this method goes to a service and calls the below FindByIdAsync
var actual = await sut.GetProfileForUserAsync(user);
// Then
Assert.Equal(10, actual.EmployeeId);
}
}
public async Task<Employee> FindByIdAsync(long id)
{
var profile = await this.repository.Set
.Include(_ => _.Address) --> IT FAILS ON THIS LINE, IF I REMOVE THE INCLUDE THEN IT WORKS
.Include(_ => _.EmployeeImage)
.SingleOrDefaultAsync(_ => _.EmployeeId == id);
if (profile == null)
{
return null;
}
return profile;
}
UPDATE
Service Layer
public class ProfileService : GenericService<Employee>, IProfileService
{
private readonly DbContextRepository<Employee> repository;
private readonly IUserService userService;
public ProfileService(DbContextRepository<Employee> repository, IUserService userService)
: base(repository)
{
this.repository = repository;
this.userService = userService;
}
public Task<Employee> GetProfileForUserAsync(ClaimsPrincipal user)
{
var id = this.userService.GetEmployeeId(user);
return id.HasValue ? this.FindByIdAsync(id.Value) : null;
}
public async Task<Employee> FindByIdAsync(long id)
{
var profile = await this.repository.Set
.Include(_ => _.Address)
.Include(_ => _.EmployeeImage)
.SingleOrDefaultAsync(_ => _.EmployeeId == id);
if (profile == null)
{
return null;
}
return profile;
}
}
Employee Model
public class Employee : IValidatableObject
{
[Key]
[Column("pkEmpID")]
public long EmployeeId { get; set; }
[Column("fkCompanyID")]
public long CompanyId { get; set; }
public virtual Company Company { get; set; }
[Display(Name = "lblEmpNumber")]
public string EmpNumber { get; set; }
public virtual IList<Address> Address { get; set; } = new List<Address>();
// WITH SOME EXTRA STUFF NOT NEEDED FOR THIS
}
Repository
public class DbContextRepository<TEntity> : IGenericRepository<TEntity>, IDisposable
where TEntity : class
{
public DbContextRepository(ApplicationContext context)
{
this.Context = context;
this.Set = context.Set<TEntity>();
this.SetWithNoTracking = this.Set.AsNoTracking();
}
public ApplicationContext Context { get; }
public DbSet<TEntity> Set { get; }
public IQueryable<TEntity> SetWithNoTracking { get; }
// WITH SOME EXTRA STUFF NOT NEEDED FOR THIS
}
Hope this will shed more light

Resources