How to select just some fields from a table in EF - asp.net-mvc

I have a table with 9 columns in database and I want to be able to load only some fields of it if I need.
How can I do this with Entity Framework 4 please?
e.g. My table has these fields:
ID, FirstName, LastName, FotherName, BirthDate, Mobile, Email
and I want to be able to fetch just these columns:
ID, FirstName, LastName
My project is an ASP.NET MVC 3 application, with SQLServer 2008 Express and EF 4.1.

Assume you have a table with this model:
public class User{
public int ID {get; set;}
public string NickName {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string FotherName {get; set;}
public DateTime BirthDate {get; set;}
public string Mobile {get; set;}
public string Email {get; set;}
public string Password {get; set;}
}
Now, you want fetch just ID, FirstName, LastName, and FotherName. You can do it in 2 way; The first way is fetch them as an anonymous object, look:
var user = entityContext.Users.Where(u => u.ID == id)
.Select(u => new {
ID = u.ID,
FirstName = u.FirstName,
LastName = u.LastName,
FotherName = u.FotherName
}).Single();
Now, your return-value-type is anonymous, you can work with it such as:
var i = user.ID;
// or
var s = user.FirstName;
In another way (for example when you want to pass the object as an Model to a View), you can define a new class, (i.e. UserViewModel), and when you select the object, select it as a UserViewModel. look:
public class UserViewModel{
public int ID {get; set;}
public string NickName {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string FotherName {get; set;}
}
and in query, take this:
var user = entityContext.Users.Where(u => u.ID == id)
.Select(u => new UserViewModel {
ID = u.ID,
FirstName = u.FirstName,
LastName = u.LastName,
FotherName = u.FotherName
}).Single();
Look that just ONE difference is between them, in labda expression, instead of u => new {}
we are using u => new UserViewModel{}. Good luck.

There can be many ways to do this job, but using Automapper NuGet package is the most simple one I have experienced.
First: Install Autmapper NuGet package for your project from NuGet package explorer.
Second: Make a simple ViewModel, which contains only required attributes:
public class UserViewModel {
public int ID {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
Third: Initialize your your mapper only for once in app_start class like:
namespace SampleProject.App_Start {
public class AutoMapperConfig {
public static void Initializer() {
AutoMapper.Mapper.Initialize(cfg => {
cfg.CreateMap<User, UserViewModel>()
});
}
}
}
Fourth: Add it's entry in Global.asax.cs:
namespace SampleProject
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// AutoMapper Initializer
App_Start.AutoMapperConfig.Initializer();
}
}
}
Fifth: Use it in your controller where you want like this:
namespace SampleProject.Controllers
{
public class UsersController : Controller
{
private DataContext db = new DataContext();
public ActionResult Index()(
var model = AutoMapper.Mapper.Map<List<UserViewModel>>(db.User.ToList());
return View(model);
}
}
}
Last: You can create as many maps as you want between your Models and ViewModels by initializing them once in the app_start's AutoMapperConfig class and use them where you want with a simple line of code.
Also you can find a lot of help about Automapper if you search about it. Its main website is here.
Important:
I am a developer of ASP.NET MVC 5. Automapper works fine for me every time. I cannot check it on MVC 3 or older than MVC 5.

Related

How to set additional [Not Mapped] properties querying the database with a property in EF Core 6 resultset class

When I query a table in my database using EF Core 6, i get a IEnumberable or a List of items, like this
public class SqlService
{
private IDbContextFactory<WebContext> CtxFactory { get; set; }
public SqlService(IDbContextFactory<WebContext> dbContextFactory)
{
CtxFactory = dbContextFactory;
}
public List<Test> WithoutMail()
{
using var ctx = CtxFactory.CreateDbContext();
return ctx.Test.Where(p => p.EMail == null).ToList();
}
}
Now my results represent instances of my class "Test" like this:
private class Test
{
public string EMail {get; set;}
public string SomeValue {get; set;}
... more properties
}
What I want is a (not mapped) property, querying the dababase with a value from one of the proerties like:
private class Test
{
public string EMail {get; set;}
public string SomeValue {get; set;}
... more properties
[NotMapped]
public string ValueFromQuery => [CTX].SomeOtherTable.Where(p => p.Value == SomeValue);
}
But of cause, I have no context here and no database service. Is this possbile? Ist this the wrong way? Should I implement another method in SQLService to handle this task?
It would be nice to "extend" the class this way with some additional proerties that come from the db depending on a value in the table.

Usage of entities and DTOs when performing read and create/update on a database

What is the proper usage of entities and DTOs when performing database actions? My mindset is that it seems best to use DTOs when reading from a database and entities when creating/updating to a database. As a small example let's consider teh following:
Book Class
public class Book/Entity
{
public int Id {get; set;}
public string Title {get; set;}
public int AuthorId {get; set;}
public Author Author {get; set;}
}
Author Class/Entity
public class Author
{
public int Id {get; set;}
public string Name {get; set;}
public int BookId {get; set;}
public Book Book {get; set;}
}
BookAuthorDto Class
public class BookAuthorDto
{
public string Title {get; set;}
public string Name {get; set;}
}
Now, let's say we have a WebApi Book controller.
public class BookController : ApiController
{
public IHttpActionResult GetBook(int id)
{
var BADto = context.Book.Where(book => book.ID == id)
.Select(book => new BookAuthorDto
{
Title = book.Title,
Name = book.Author.Name
});
return Ok<BookAuthorDto>(BADto);
}
public IHttpActionResult PostBookEntity(Book book)
{
// Code for saving book to DB
}
public IHttpActionResult PostBookDto(BookAuthorDto BADto)
{
// Code for creating entities from DTO
// Code for saving the created entities to Database
}
}
Which method is considered more "proper" the PostBookEntity method, or the PostBookDto Method?
Actually it is a good idea to separate queries from data modifications (insert, update, delete) - this is called Command Query Responsibility Segregation pattern (CQRS).
Here are some great posts from experts
An introduction to CQRS by M.Fowler
Some good reasoning on why Entities + Dto's are better than just using Entities for all cases
Entities pretty much are DTOs. Use the entity for all database access, and use view models in your actions.

Breeze - properties of an expanded navigation property

Environment:
Breeze 1.4.16
Durandal 2.1.0
EF 6.1.1
Consider the following classes Account, Activity, and User. Let's call it a simple CRM scenario where a user creates sales activities for an account in their portfolio.
public class Account
{
public int Id {get; set;}
public ICollection<Activity> Activities {get; set;}
}
public class Activity
{
public int Id {get; set;}
public DateTime ActivityDate {get; set;}
public int AccountId {get; set;}
[ForeignKey("AccountId")]
public Account Account {get; set;}
public int CreatedById {get; set;}
[ForeignKey("CreatedById ")]
public User CreatedBy {get; set;}
}
public class User
{
public int Id {get; set;}
public string Name {get; set;}
}
I'm struggling to write a breeze query which when retrieving an Account, expands the related Activity entity to give me the Name of the user who entered the activity.
The following query works, however the createdBy property of each activity entity is always null:
var query = breeze.EntityQuery
.from("getAccount")
.withParameters({ id: id })
.expand("Activities");
Reading through the breeze documentation on Navigation Properties at: http://www.breezejs.com/documentation/navigation-properties, this seems close to the "OrderDetails.Product" scenario so I rewrote the query as follows:
This query throws an exception when I execute it.
var query = breeze.EntityQuery
.from("getAccount")
.withParameters({ id: id })
.expand("Activities.CreatedBy");

Integrating data from multiple objects in one view in MVC4

Hi I have three classes as objects which go into the database.
public class Employees
{
public int Id { get; set;}
public string Name { get; set;}
public string SocialSecurityNumber{ get; set;}
public DateTime DateOfBirth { get; set;}
}
public class Education
{
public int Id { get; set;}
public string EmployeeId { get; set;}
public string EducationLevel{ get; set;} // this will be a drop down list
public string University { get; set;}
public string FieldOfStudy { get; set;}
}
public class Experience
{
public int Id { get; set;}
public int EmployeeId { get; set;}
public string Employer{ get; set;}
public DateTime From { get; set;}
public DateTime To { get; set;}
public string JobRole { get; set;}
}
Then I have the DBContext class defined as:
public class AppDb : DbContext
{
public DbSet<Employee>Employees{ get; set;}
public DbSet<Education> Educations { get; set;}
public DbSet<Experience> Experiences {get; set;}
}
What my app needs to do now is offer a Create Employee form on the home page which lets the user fill in all the details pertaining to him. That is Employee details , Education and Experience against the employee object in one single form in Home/Index View.
Any help will be appreciated.
Create new class in the Model folder.
Add 3 properties for Employees, Education and Experience and build your project.
In the action method in the controller (Index for example), fill that class with your data and 'return View(yourFilledClass)'
right click on the controller method (Index) and add View
Bind that view to the new class and select Details in the dropdown
Now you have a view for displaying all the details of the new class you've just populated
It's quite the same for Edit, delete and add
Hope it helps :)

MVC Filter Database with IIdentity

In my MVC Site a Teacher login and should view his classes and all books used in his classes.
The teacher should not be able to see someone else class or book.
Here's my model
public class Teacher
{
public int Id { get; set; }
public string Name {get; set;}
}
public class Books
{
public int Id {get; set;}
public string Title {get; set;}
public int CourseId {get; set;}
}
public class Course
{
public int Id {get; set;}
public int Name {get; set;}
public int TeacherId {get; set;}
}
I use a RepositoryPattern with UnitOfWork.
In order to get all classes tobe showned I should put in my Controller this kind of line :
var classes = classRepository.All.Where(x => x.TeacherId == currentTeacher.Id)
Things will get worst with the BookControler since I need to check all classes of the currentTeacher:
var classes = classRepository.All.Where(x => x.TeacherId == currentTeacher.Id)
var books = bookRepository.All.Where(x => classes.Contains(y => y.Id == x.CourseId)
It seems to me that this kind of approach may lead to some functional bug.
what I would like to do is that when a teacher login my repositories auto-filter in order to keep only datas concerning the currentTeacher, therefore in my controller I would have :
var classes = classRepository.All; // Already filtered on currentTeacher
or
var books = bookRepository.All; // Already filtered on currentTeacher
Is this possible? And how?
Create a new All(IPrincipal user) method in which you pass in the current authenticated user. This All method will lookup the Identity.Name value in your object context's Teacher collection to get the ID which is then returned.
i.e. .Where(x => x.TeacherId == currentTeacher.Id) is the return value from this new All method.

Resources