Get items count from OData api - asp.net

I'm working on ASP.NET Core 3.1 project where I use OData for the rest api. The problem is that when I try to fetch the count of the items in the collection with this query: http://someurl?$count=true, OData returns me an array of all the items, instead of the count. I read a lot of articles about OData and nothing helped, so I'm quite confused.

Here is a working demo , you could refer to
Install Package Microsoft.AspNetCore.OData -Version 7.4.0
Model
public class Student
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Score { get; set; }
}
Controller , EnableQuery attribute enables an endpoint to have OData capabilities
[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
[HttpGet]
[EnableQuery()]
public IEnumerable<Student> Get()
{
return new List<Student>
{
new Student
{
Id = Guid.NewGuid(),
Name = "Vishwa Goli",
Score = 100
},
new Student
{
Id = Guid.NewGuid(),
Name = "Josh McCall",
Score = 120
}
};
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(mvcOptions =>
mvcOptions.EnableEndpointRouting = false);
services.AddOData();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapControllers();
//});
app.UseMvc(routeBuilder =>
{
// enable Selection, Expansion, Count, Filter, OrderBy for all routes under “odata/”
routeBuilder.Expand().Select().Count().OrderBy().Filter();
routeBuilder.MapODataServiceRoute("odata", "odata", GetEdmModel());
});
}
private IEdmModel GetEdmModel()
{
var edmBuilder = new ODataConventionModelBuilder();
edmBuilder.EntitySet<Student>("Students");
return edmBuilder.GetEdmModel();
}
Result:
Reference:
https://devblogs.microsoft.com/odata/experimenting-with-odata-in-asp-net-core-3-1/
https://medium.com/#sddkal/using-odata-controller-in-net-core-apis-63b688585eaf

Related

Keep getting SqlException: Cannot insert explicit value for identity column in table 'Movie' when IDENTITY_INSERT is set to OFF

I'm working on a program that I take an excel file to a SQL database. I'm using EPPlus -Version 4.5.2.1. I keep getting errors when I import excel file Movie. SqlException: Cannot insert explicit value for identity column in table 'Movie' when IDENTITY_INSERT is set to OFF. DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
WebApplication14.Controllers.HomeController.Import(IFormFile file) in HomeController.cs
+
await _dbContext.SaveChangesAsync();
The HomeController Code:
namespace WebApplication14.Controllers
{
public class HomeController : Controller
{
private readonly ApplicationDbContext _dbContext;
public HomeController(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<Movie>> Import(IFormFile file)
{
var list = new List<Movie>();
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
using (var package = new ExcelPackage(stream))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
var colcount = worksheet.Dimension.Columns;
for (int row = 2; row < rowcount; row++)
{
list.Add(new Movie
{
Id = int.Parse(worksheet.Cells[row, 1].Value.ToString().Trim()),
Title = worksheet.Cells[row, 2].Value.ToString().Trim(),
Genre = worksheet.Cells[row, 3].Value.ToString().Trim()
});
}
}
}
//SaveDataToDb(list);
_dbContext.Movie.AddRange(list);
await _dbContext.Database.ExecuteSqlCommandAsync(#"SET IDENTITY_INSERT [MovieList-1].[dbo].[Movie] ON");
await _dbContext.SaveChangesAsync();
await _dbContext.Database.ExecuteSqlCommandAsync(#"SET IDENTITY_INSERT [MovieList-1].[dbo].[Movie] OFF");
return list;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
Model Movie
namespace WebApplication14.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public string Genre { get; set; }
}
}
DbContext Code
namespace WebApplication14.Models
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Movie> Movie { get; set; }
}
}
My Migration Code
public partial class MoviesToDb : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(nullable: true),
Genre = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
Startup Code
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
My AppSettings.Json ConnectionString
"ConnectionStrings": {
"DefaultConnection": "Server=localhost\\SQLEXPRESS;Database=MovieList-1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
View/Home/Index
#{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about building Web apps with ASP.NET Core.</p>
<div class="container">
<form method="post" asp-controller="Home" asp-action="Import" enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit">Import From Excel</button>
</form>
</div>
</div>
EF will open and close the connection after each operation by default. This causes the SqlConnection to be returned to the Connection Pool, and its state is cleared, including dropping temp tables, and resetting session-level SET setting, each time it's fetched from the pool.
If you explicitly open the DbContext's connection (or start a transaction), the IDENTITY_INSERT setting should still be in effect when you call SaveChanges():
_dbContext.Database.OpenConnection();
_dbContext.Movie.AddRange(list);
await _dbContext.Database.ExecuteSqlCommandAsync(#"SET IDENTITY_INSERT [MovieList-1].[dbo].[Movie] ON");
await _dbContext.SaveChangesAsync();
await _dbContext.Database.ExecuteSqlCommandAsync(#"SET IDENTITY_INSERT [MovieList-1].[dbo].[Movie] OFF");

.Net Core Odata response missed metadata values

Im using Odata on my old project with .NET Framework, and response from it like this:
{
"#odata.context": "http://localhost:5000/api/$metadata#TestController",
"#odata.count": 0,
"value": []
}
Here is a metadata of odata and prop "value" contains response data.
But when I tried to install Odata into my new project on .NET Core 3.1, it works, but response from it like this:
{
//some data
}
I haven't got odata metadata velues. I want that responses from all projects were similar. Can't find information how to add|turn on metadata into my .Net core response
It could work well in my asp.net core 3.1 project,here is a working demo like below:
1.Install Microsoft.AspNetCore.OData package version 7.5.2.
2.Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddOData();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.Select().Filter().OrderBy().Count().MaxTop(10);
endpoints.MapODataRoute("api", "api", GetEdmModel());
});
}
private IEdmModel GetEdmModel()
{
var odataBuilder = new ODataConventionModelBuilder();
odataBuilder.EntitySet<WeatherForecast>("WeatherForecast");
return odataBuilder.GetEdmModel();
}
3.Model:
public class WeatherForecast
{
public Guid Id { get; set; } //must have a key
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
4.Controller(comment on Route attribute and ApiController attribute):
//[ApiController]
//[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[EnableQuery]
[HttpGet]
public async Task<IEnumerable<WeatherForecast>> GetAsync()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
Result:

Why my Entity Framework Core Database-First Model Custom Changes Gone After Re-Scaffold? Any Solution

I am working with ASP.Net Core 2.1 & I am facing a problem. I have been working on implementing a Database-First application. The initial Scaffold-DbContext command works just fine and creates all my entities correctly. After that, I make some changes to model files for Validation. My DBA made a new change on DB so I re-Scaffold the DB. Then I notice that re-scaffold overwrites all the custom code I have added to all the model files.
Is there any way I re-scaffold the DB but that only changes those files changes by DBA in ASP.Net Core DB First Approach?
Every time I am facing this problem.
I Re-scaffold with the below command:
Scaffold-DbContext "Server=192.168.46.101;Database=DBNAME;User Id=USERID;Password=PASSWORD" Microsoft.EntityFrameworkCore.SqlServer -ContextDir Data -OutputDir Models -UseDatabaseNames -force
My Custom Added Annotation to Model:
//Custom Annotation
[Key]
public int COLORCODE { get; set; }
//Custom Validation
[Required(ErrorMessage = "Color Name can not be empty")]
public string COLOR { get; set; }
public string REMARKS { get; set; }
After Re-scaffolding my code be like:
public int COLORCODE { get; set; }
public string COLOR { get; set; }
public string REMARKS { get; set; }
My Program.cs File:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
logging.AddNLog();
})
.UseStartup<Startup>();
}
My Startup.cs File:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureApplicationCookie(options =>
{
options.AccessDeniedPath = new PathString("/Administrator/AccessDenied");
});
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
// options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<Context>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("ConnectionName")));
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 15;
options.Password.RequiredUniqueChars = 5;
options.Password.RequireNonAlphanumeric = false;
options.SignIn.RequireConfirmedEmail = true;
options.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
})
.AddEntityFrameworkStores<Context>()
.AddDefaultTokenProviders()
.AddTokenProvider<CustomEmailConfirmationTokenProvider<IdentityUser>>("CustomEmailConfirmation");
// REGISTER ExtractEMService
ExtractEMService.ExtractEMRegisterService(services);
//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseStatusCodePagesWithReExecute("/Error/{0}");
//app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Basic}/{action=BasicColors}/{id?}");
});
}
}
There is no way you can do that, but just leave the generated classes as is and use a buddy class for the data annotations:
[MetadataType(typeof(MetaData))]
public partial class Person
{
public class MetaData
{
[Required]
[Display(Name = "Enter Your Name")]
public string FirstName;
}
}
https://ryanhayes.net/data-annotations-for-entity-framework-4-entities-as-an-mvc-model/

Automapper - Mapper already initialized error

I am using AutoMapper 6.2.0 in my ASP.NET MVC 5 application.
When I call my view through controller it shows all things right. But, when I refresh that view, Visual Studio shows an error:
System.InvalidOperationException: 'Mapper already initialized. You must call Initialize once per application domain/process.'
I am using AutoMapper only in one controller. Not made any configuration in any place yet nor used AutoMapper in any other service or controller.
My controller:
public class StudentsController : Controller
{
private DataContext db = new DataContext();
// GET: Students
public ActionResult Index([Form] QueryOptions queryOptions)
{
var students = db.Students.Include(s => s.Father);
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Student, StudentViewModel>();
});
return View(new ResulList<StudentViewModel> {
QueryOptions = queryOptions,
Model = AutoMapper.Mapper.Map<List<Student>,List<StudentViewModel>>(students.ToList())
});
}
// Other Methods are deleted for ease...
Error within controller:
My Model class:
public class Student
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string CNIC { get; set; }
public string FormNo { get; set; }
public string PreviousEducaton { get; set; }
public string DOB { get; set; }
public int AdmissionYear { get; set; }
public virtual Father Father { get; set; }
public virtual Sarparast Sarparast { get; set; }
public virtual Zamin Zamin { get; set; }
public virtual ICollection<MulaqatiMehram> MulaqatiMehram { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
My ViewModel Class:
public class StudentViewModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string CNIC { get; set; }
public string FormNo { get; set; }
public string PreviousEducaton { get; set; }
public string DOB { get; set; }
public int AdmissionYear { get; set; }
public virtual FatherViewModel Father { get; set; }
public virtual SarparastViewModel Sarparast { get; set; }
public virtual ZaminViewModel Zamin { get; set; }
}
If you want/need to stick with the static implementation in a unit testing scenario, note that you can call AutoMapper.Mapper.Reset() before calling initialize. Do note that this should not be used in production code as noted in the documentation.
Source: AutoMapper documentation.
When you refresh the view you are creating a new instance of the StudentsController -- and therefore reinitializing your Mapper -- resulting in the error message "Mapper already initialized".
From the Getting Started Guide
Where do I configure AutoMapper?
If you're using the static Mapper method, configuration should only happen once per AppDomain. That means the best place to put the configuration code is in application startup, such as the Global.asax file for ASP.NET applications.
One way to set this up is to place all of your mapping configurations into a static method.
App_Start/AutoMapperConfig.cs:
public class AutoMapperConfig
{
public static void Initialize()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Student, StudentViewModel>();
...
});
}
}
Then call this method in the Global.asax.cs
protected void Application_Start()
{
App_Start.AutoMapperConfig.Initialize();
}
Now you can (re)use it in your controller actions.
public class StudentsController : Controller
{
public ActionResult Index(int id)
{
var query = db.Students.Where(...);
var students = AutoMapper.Mapper.Map<List<StudentViewModel>>(query.ToList());
return View(students);
}
}
I've used this method before and it worked till version 6.1.1
Mapper.Initialize(cfg => cfg.CreateMap<ContactModel, ContactModel>()
.ConstructUsing(x => new ContactModel(LoggingDelegate))
.ForMember(x => x.EntityReference, opt => opt.Ignore())
);
Since version 6.2, this doesn't work any more. To correctly use Automapper create a new Mapper and us this one like this:
var mapper = new MapperConfiguration(cfg => cfg.CreateMap<ContactModel, ContactModel>()
.ConstructUsing(x => new ContactModel(LoggingDelegate))
.ForMember(x => x.EntityReference, opt => opt.Ignore())).CreateMapper();
var model = mapper.Map<ContactModel>(this);
In case you really need to "re-initialize" AutoMapper you should switch to the instance based API to avoid System.InvalidOperationException: Mapper already initialized. You must call Initialize once per application domain/process.
For example, when you are creating the TestServer for xUnit tests you can just set ServiceCollectionExtensions.UseStaticRegistration inside fixure class constructor to false to make the trick:
public TestServerFixture()
{
ServiceCollectionExtensions.UseStaticRegistration = false; // <-- HERE
var hostBuilder = new WebHostBuilder()
.UseEnvironment("Testing")
.UseStartup<Startup>();
Server = new TestServer(hostBuilder);
Client = Server.CreateClient();
}
For Unit Testing, you can add Mapper.Reset() to your unit test class
[TearDown]
public void TearDown()
{
Mapper.Reset();
}
You can use automapper as Static API and Instance API ,
Mapper already initialized is common issue in Static API , you can use mapper.Reset()
where you initialized mapper but this this not an answer at all.
Just try with instance API
var students = db.Students.Include(s => s.Father);
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Student, StudentViewModel>();
});
IMapper iMapper = config.CreateMapper();
return iMapper.Map<List<Student>, List<StudentViewModel>>(students);
Automapper 8.0.0 version
AutoMapper.Mapper.Reset();
Mapper.Initialize(
cfg => {
cfg.CreateMap<sourceModel,targetModel>();
}
);
You can simply use Mapper.Reset().
Example:
public static TDestination MapToObject<TSource, TDestination>(TSource Obj)
{
Mapper.Initialize(cfg => cfg.CreateMap<TSource, TDestination>());
TDestination tDestination = Mapper.Map<TDestination>(Obj);
Mapper.Reset();
return tDestination;
}
If you are using MsTest you can use the AssemblyInitialize attribute so that mapping gets configured only once for that assembly (here test assembly). This is generally added into to the base class of controller unit tests.
[TestClass]
public class BaseUnitTest
{
[AssemblyInitialize]
public static void AssemblyInit(TestContext context)
{
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Source, Destination>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.EmailAddress));
});
}
}
I hope this answer helps
If you are using Mapper in UnitTest and your tests more then one, You may use Mapper.Reset()
`
//Your mapping.
public static void Initialize()
{
Mapper.Reset();
Mapper.Initialize(cfg =>
{
cfg.CreateMap<***>
}
//Your test classes.
[TestInitialize()]
public void Initialize()
{
AutoMapping.Initialize();
}`
private static bool _mapperIsInitialized = false;
public InventoryController()
{
if (!_mapperIsInitialized)
{
_mapperIsInitialized = true;
Mapper.Initialize(
cfg =>
{
cfg.CreateMap<Inventory, Inventory>()
.ForMember(x => x.Orders, opt => opt.Ignore());
}
);
}
}

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