I have been experimenting a little with Entity Framework, and after facing the error below, I tried using ThenInclude to resolve it.
The expression '[x].ModelA.ModelB' passed to the Include operator could not be bound
But now it seems I lack some understanding of why it did solve the problem
What's the difference between this:
.Include(x => x.ModelA.ModelB)
And this:
.Include(x => x.ModelA).ThenInclude(x => x.ModelB)
"Include" works well with list of object, but if you need to get multi-level data, then "ThenInclude" is the best fit. Let me explain it with an example. Say we have two entities, Company and Client:
public class Company
{
public string Name { get; set; }
public string Location { get; set; }
public List<Client> Clients {get;set;}
}
public class Client
{
public string Name { get; set; }
public string Domains { get; set; }
public List<string> CountriesOfOperation { get; set; }
}
Now if you want just companies and the entire client list of that company, you can just use "Include":
using (var context = new YourContext())
{
var customers = context.Companies
.Include(c => c.Clients)
.ToList();
}
But if you want a Company with "CountriesOfOperation" as related data, you can use "ThenInclude" after including Clients like below:
using (var context = new MyContext())
{
var customers = context.Companies
.Include(i => i.Clients)
.ThenInclude(a => a.CountriesOfOperation)
.ToList();
}
The difference is that Include will reference the table you are originally querying on regardless of where it is placed in the chain, while ThenInclude will reference the last table included. This means that you would not be able to include anything from your second table if you only used Include.
Related
Looking at this documentation I can see that you can load multiple navigation entities using the following syntax:
using (var context = new DbContext())
{
var userDocs = context.UserDocuments
.Include(userDoc => userDoc.Role.User)
.ToList();
}
This will give me Role and User navigation properties hung off my UserDocument object, however if I want to use the string overload of Include, how might I construct the code to handle multiple includes?
This does not work:
return await ctx.UserDocuments.Where(x => x.UserId == userId)
.Include("Role.User").ToList();
I am trying to do it this way as my methods may want some, all or no navigation properties returned depending on the calling code. My intention is to add a string array to the repository method which will build any required navigation properties accordingly. If this is the wrong approach, does anyone have another recommendation, I'm wondering if lazy loading would be a more elegant solution...?
Edit
This is the Entity which has nav props:
public partial class UserDocument
{
public int Id { get; set; }
public Guid UserId { get; set; }
public int RoleId { get; set; }
public int AccountId { get; set; }
public virtual Role Role { get; set; } = null!;
public virtual User User { get; set; } = null!;
}
I think you are looking for something like this:
public async Task<List<UserDocument>> MyMethod(List<string> propertiesToInclude)
{
IQueryable<UserDocument> currentQuery = _context.UserDocuments.Where(x => x.UserId == userId);
foreach(var property in propertiesToInclude)
{
currentQuery = currentQuery.Include(property);
}
return await currentQuery.ToListAsync();
}
If you're using the Include(String) method, you don't need to include the lambda to specify the property path.
Instead of doing .Include(x => "Role.User"), try .Include("Role.User")
First of all, you must told us what is "Role.User"?
We cannot answer you if we don't know excactly what you wrote.
So, now we are know that are two differents entities you can do this one
var userDocs = await context.UserDocuments
.Include(x => x.Role)
.ThenInclude(x => x.User)
.ToListAsync();
I hope this one helps you. :)
I need to fetch from the database this:
rack
it's type
single shelf with all its boxes and their box types
single shelf above the previous shelf without boxes and with shelf type
Shelves have VerticalPosition which is in centimeters from the ground - when I am querying for e.g. second shelf in rack, I need to order them and select shelf on index 1.
I have this ugly EF query now:
var targetShelf = await _warehouseContext.Shelves
.Include(s => s.Rack)
.ThenInclude(r => r.Shelves)
.ThenInclude(s => s.Type)
.Include(s => s.Rack)
.ThenInclude(r => r.Type)
.Include(s => s.Rack)
.ThenInclude(r => r.Shelves)
.Include(s => s.Boxes)
.ThenInclude(b => b.BoxType)
.Where(s => s.Rack.Aisle.Room.Number == targetPosition.Room)
.Where(s => s.Rack.Aisle.Letter == targetPosition.Aisle)
.Where(s => s.Rack.Position == targetPosition.Rack)
.OrderBy(s => s.VerticalPosition)
.Skip(targetPosition.ShelfNumber - 1)
.FirstOrDefaultAsync();
but this gets all boxes from all shelves and it also shows warning
Compiling a query which loads related collections for more than one collection navigation, either via 'Include' or through projection, but no 'QuerySplittingBehavior' has been configured. By default, Entity Framework will use 'QuerySplittingBehavior.SingleQuery', which can potentially result in slow query performance.
Also I would like to use AsNoTracking(), because I don't need change tracker for these data.
First thing: for AsNoTracking() I would need to query Racks, because it complains about circular include.
Second thing: I tried conditional include like this:
.Include(r => r.Shelves)
.ThenInclude(s => s.Boxes.Where(b => b.ShelfId == b.Shelf.Rack.Shelves.OrderBy(sh => sh.VerticalPosition).Skip(shelfNumberFromGround - 1).First().Id))
but this won't even translate to SQL.
I have also thought of two queries - one will retrieve rack with shelves and second only boxes, but I still wonder if there is some single call command for this.
Entities:
public class Rack
{
public Guid Id { get; set; }
public Guid RackTypeId { get; set; }
public RackType Type { get; set; }
public ICollection<Shelf> Shelves { get; set; }
}
public class RackType
{
public Guid Id { get; set; }
public ICollection<Rack> Racks { get; set; }
}
public class Shelf
{
public Guid Id { get; set; }
public Guid ShelfTypeId { get; set; }
public Guid RackId { get; set; }
public int VerticalPosition { get; set; }
public ShelfType Type { get; set; }
public Rack Rack { get; set; }
public ICollection<Box> Boxes { get; set; }
}
public class ShelfType
{
public Guid Id { get; set; }
public ICollection<Shelf> Shelves { get; set; }
}
public class Box
{
public Guid Id { get; set; }
public Guid ShelfId { get; set; }
public Guid BoxTypeId { get; set; }
public BoxType BoxType { get; set; }
public Shelf Shelf { get; set; }
}
public class BoxType
{
public Guid Id { get; set; }
public ICollection<Box> Boxes { get; set; }
}
I hope I explained it good enough.
Query Splitting
First, I'd recommend benchmarking the query as-is before deciding whether to attempt any optimization.
It can be faster to perform multiple queries than one large query with many joins. While you avoid a single complex query, you have additional network round-trips if your DB isn't on the same machine, and some databases (e.g. SQL Server without MARS enabled) only support one active query at a time. Your mileage may vary in terms of actual performance.
Databases do not generally guarantee consistency between separate queries (SQL Server allows you to mitigate that with the performance-expensive options of serializable or snapshot transactions). You should be cautious using a multiple-query strategy if intervening data modifications are possible.
To split a specific query, use the AsSplitQuery() extension method.
To use split queries for all queries against a given DB context,
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(
#"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;ConnectRetryCount=0",
o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery));
}
Reference.
Query that won't translate
.Include(r => r.Shelves)
.ThenInclude(s => s.Boxes.Where(b => b.ShelfId == b.Shelf.Rack.Shelves.OrderBy(sh => sh.VerticalPosition).Skip(shelfNumberFromGround - 1).First().Id))
Your expression
s.Boxes.Where(b => b.ShelfId == b.Shelf.Rack.Shelves.OrderBy(sh => sh.VerticalPosition).Skip(shelfNumberFromGround - 1).First().Id
resolves to an Id. ThenInclude() expects an expression that ultimately specifies a collection navigation (in other words, a table).
Ok, from your question I'm assuming you have a method where you need these bits of information:
single shelf with all its boxes and their box types
single shelf above the previous shelf without boxes and with shelf type
rack and it's type
Whether EF breaks up the queries or you do doesn't really make much of a difference performance-wise. What matters is how well the code is later understood and can adapt if/when requirements change.
The first step I would recommend is to identify the scope of detail you actually need. You mention that you don't need tracking, so I would expect you intend to deliver these results or otherwise consume the information without persisting changes. Project this down to just the details from the various tables that you need to be served by a DTO or ViewModel, or an anonymous type if the data doesn't really need to travel. For instance you will have a shelf & shelf type which is effectively a many-to-one so the shelf type details can probably be part of the shelf results. Same with the Box and BoxType details. A shelf would then have an optional set of applicable box details. The Rack & Racktype details can come back with one of the shelf queries.
[Serializable]
public class RackDTO
{
public int RackId { get; set; }
public int RackTypeId { get; set; }
public string RackTypeName { get; set; }
}
[Serializable]
public class ShelfDTO
{
public int ShelfId { get; set; }
public int VerticalPosition { get; set; }
public int ShelfTypeId { get; set; }
public string ShelfTypeName { get; set; }
public ICollection<BoxDTO> Boxes { get; set; } = new List<BoxDTO>();
public RackDTO Rack { get; set; }
}
[Serializable]
public class BoxDTO
{
public int BoxId { get; set; }
public int BoxTypeId { get; set; }
public string BoxTypeName { get; set; }
}
Then when reading the information, I'd probably split it into two queries. One to get the "main" shelf, then a second optional one to get the "previous" one if applicable.
ShelfDTO shelf = await _warehouseContext.Shelves
.Where(s => s.Rack.Aisle.Room.Number == targetPosition.Room
&& s.Rack.Aisle.Letter == targetPosition.Aisle
&& s.Rack.Position == targetPosition.Rack)
.Select(s => new ShelfDTO
{
ShelfId = s.ShelfId,
VerticalPosition = s.VerticalPosition,
ShelfTypeId = s.ShelfType.ShelfTypeId,
ShelfTypeName = s.ShelfType.Name,
Rack = s.Rack.Select(r => new RackDTO
{
RackId = r.RackId,
RackTypeId = r.RackType.RackTypeId,
RackTypeName = r.RackType.Name
}).Single(),
Boxes = s.Boxes.Select(b => new BoxDTO
{
BoxId = b.BoxId,
BoxTypeId = b.BoxType.BoxTypeId,
BoxTypeName = b.BoxType.Name
}).ToList()
}).OrderBy(s => s.VerticalPosition)
.Skip(targetPosition.ShelfNumber - 1)
.FirstOrDefaultAsync();
ShelfDTO previousShelf = null;
if (targetPosition.ShelfNumber > 1 && shelf != null)
{
previousShelf = await _warehouseContext.Shelves
.Where(s => s.Rack.RackId == shelf.RackId
&& s.VerticalPosition < shelf.VerticalPosition)
.Select(s => new ShelfDTO
{
ShelfId = s.ShelfId,
VerticalPosition = s.VerticalPosition,
ShelfTypeId = s.ShelfType.ShelfTypeId,
ShelfTypeName = s.ShelfType.Name,
Rack = s.Rack.Select(r => new RackDTO
{
RackId = r.RackId,
RackTypeId = r.RackType.RackTypeId,
RackTypeName = r.RackType.Name
}).Single()
}).OrderByDescending(s => s.VerticalPosition)
.FirstOrDefaultAsync();
}
Two fairly simple to read queries that should return what you need without much problem. Because we project down to a DTO we don't need to worry about eager loading and potential cyclical references if we wanted to load an entire detached graph. Obviously this would need to be fleshed out to include the details from the shelf, box, and rack that are relevant to the consuming code/view. This can be trimmed down even more by leveraging Automapper and it's ProjectTo method to take the place of that whole Select projection as a one-liner.
In SQL raw it could look like
WITH x AS(
SELECT
r.*, s.Id as ShelfId, s.Type as ShelfType
ROW_NUMBER() OVER(ORDER BY s.verticalposition) as shelfnum
FROM
rooms
JOIN aisles on aisles.RoomId = rooms.Id
JOIN racks r on r.AisleId = aisles.Id
JOIN shelves s ON s.RackId = r.Id
WHERE
rooms.Number = #roomnum AND
aisles.Letter = #let AND
r.Position = #pos
)
SELECT *
FROM
x
LEFT JOIN boxes b
ON
b.ShelfId = x.ShelfId AND x.ShelfNum = #shelfnum
WHERE
x.ShelfNum BETWEEN #shelfnum AND #shelfnum+1
The WITH uses room/aisle/rack joins to locate the rack; you seem to have these identifiers. Shelves are numbered in increasing height off ground. Outside the WITH, boxes are left joined only if they are on the shelf you want, but two shelves are returned; the shelf you want with all it's boxes and the shelf above but box data will be null because the left join fails
As an opinion, if your query is getting this level of depth, you might want to consider either using views as a shortcut in your database or use No-SQL as a read store.
Having to do lots of joins, and doing taxing operations like order by during runtime with LINQ is something I'd try my best to avoid.
So I'd approach this as a design problem, rather than a code/query problem.
In EF, All related entities loaded with Include, ThenInclude etc. produce joins on the database end. This means that when we load related master tables, the list values will get duplicated across all records, thus causing what is called "cartesian explosion". Due to this, there was a need to split huge queries into multiple calls, and eventually .AsSplitQuery() was introduced.
Eg:
var query = Context.DataSet<Transactions>()
.Include(x => x.Master1)
.Include(x => x.Master2)
.Include(x => x.Master3)
.ThenInclude(x => x.Master3.Masterx)
.Where(expression).ToListAsync();
Here we can introduce splitquery
var query = Context.DataSet<Transactions>()
.Include(x => x.Master1)
.Include(x => x.Master2)
.Include(x => x.Master3)
.ThenInclude(x => x.Master3.Masterx)
.Where(expression).AsSplitQuery.ToListAsync();
As an alternate to include this to all existing queries, which could be time consuming, we could specify this globally like
services.AddDbContextPool<EntityDataLayer.ApplicationDbContext>(options =>
{
options.EnableSensitiveDataLogging(true);
options.UseMySql(mySqlConnectionStr,
ServerVersion.AutoDetect(mySqlConnectionStr), x =>
x.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
x.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null));
});
This will ensure that all queries are called as split queries.
Now in case we need single query, we can just override this by stating single query explicitly in individual queries. This may be done vice-versa though.
var data = await query.AsSingleQuery().ToListAsync();
I need your help
I try to create a linq sentence with .Include but my problem is that i have a property in mi class witch is a list, it is my class specifically:
public partial class document
{
public int ID { get; set; }
public string Amount { get; set; }
public List<Log> Log { get; set; }
}
this is the class log
public partial class Log
{
[Key]
public int ID { get; set; }
[Required]
public Status Status { get; set; }
[Column(TypeName = "text")]
public string Description { get; set; }
public DateTime? DateLog { get; set; }
public int? DocumentID{ get; set; }
[ForeignKey("DocumentID")]
public Document Document{ get; set; }
}
my problem is that I don't know how to filter my list record inside the document for include in the class, I need to get the whole document class and filter the log that only shows status = recieved, a document can have many logs
y tried to do that but it didnĀ“t work
var Result = db.document
.Include(m => m.Log.Where(c => c.Status == Status.Recieved));
i recived the next error
"the include path expression must refer to a navigation property defined on the type. use dotted paths for reference navigation properties and the select operator for collection navigation properties.\r\nparameter name: path"
I appreciate your help
Include used for include relationships with an entity and fetch related entity properties, check documentation - Fetching related data
If you select documents without Include like this
var documents = await db.document.ToListAsync();
you get documents data where Log will be null.
You need something like that:
var result = await db.document
.Select(w=> new
{
document = w,
log = w.Log.Where(c => c.Status == Status.Recieved).ToList()
}).ToListAsync();
EF does support some automatic filtering rules to help with concepts like soft-delete (IsActive) and multi-tenancy (ClientId), but not really applicable for scenarios like this where you want to apply a situational filter like "received" documents.
EF entities should be considered as models reflecting the data state. To filter results like that is more of a view model state which you can achieve through projection:
var result = db.document.Select(d => new DocumentViewModel
{
DocumentId = d.DocumentId,
// .. fill in other required details...
ReceivedLogs = d.Logs
.Where(l => l.Status == Status.Received)
.Select(l => new LogViewModel
{
// Fill needed log details...
}).ToList()
}).ToList();
Otherwise if you are doing something local with the entities and just want the document and the received log entries:
var documentDetails = db.document
.Where(d => d.DocumentId == documentId)
.Select(d => new
{
Document = d,
ReceivedLogs = d.Logs
.Where(l => l.Status == Status.Received)
.ToList()
}).Single();
documentDetails.Document.Logs will not be eager loaded, and would trigger lazy loading if you access it, but the documentDetails does contain the relevant Received logs to access. As an anonymous type it's not suitable to being returned, only consumed locally.
I can include only related entities.
using (var context = new BloggingContext())
{
// Load all blogs, all related posts
var blogs1 = context.Blogs
.Include(b => b.Posts)
.ToList();
}
However, I don't need entire BlogPost entity. I'm interested only in particular properties, e.g:
using (var context = new BloggingContext())
{
// Load all blogs, all and titles of related posts
var blogs2 = context.Blogs
.Include(b => b.Posts.Select(p => p.Title) //throws runtime exeption
.ToList();
foreach(var blogPost in blogs2.SelectMany(b => b.Posts))
{
Console.Writeline(blogPost.Blog.Id); //I need the object graph
Console.WriteLine(blogPost.Title); //writes title
Console.WriteLine(blogPost.Content); //writes null
}
}
You either use Include which loads the entire entity, or you project what you need to a .Select:
var blogs2 = context.Blogs
.Select(x => new
{
BlogName = x.BlogName, //whatever
PostTitles = x.Post.Select(y => y.Title).ToArray()
})
.ToList();
Or, you could do something like this:
var blogs2 = context.Blogs
.Select(x => new
{
Blog = x,
PostTitles = x.Post.Select(y => y.Title).ToArray()
})
.ToList();
A Select is always better when you don't need the entire child, as it prevents querying unneeded data.
In fact what you want is: split an entity in a common, representational part and a special part that you don't always want to pull from the database. This is not an uncommon requirement. Think of products and images, files and their content, or employees with public and private data.
Entity framework core supports two ways to achieve this: owned type and table splitting.
Owned type
An owned type is a type that's wrapped in another type. It can only be accessed through its owner. This is what it looks like:
public class Post
{
public int ID { get; set; }
public Blog Blog { get; set; }
public string Title { get; set; }
public PostContent Content { get; set; }
}
public class PostContent
{
public string Content { get; set; }
}
And the owned-type mapping:
modelBuilder.Entity<Post>().OwnsOne(e => e.Content);
Where Blog is
public class Blog
{
public Blog()
{
Posts = new HashSet<Post>();
}
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Post> Posts { get; set; }
}
However, as per the docs:
When querying the owner the owned types will be included by default.
Which means that a statement like...
var posts = context.Posts.ToList();
...will always get you posts and their contents. Therefore, owned type is probably not the right approach for you. I still mentioned it, because I found out that when Posts are Included...
var blogs = context.Blogs.Include(b => b.Posts).ToList();
...the owned types, PostContents, are not included (DISCLAIMER: I'm not sure if this is a bug or a feature...). In this case, when the owned types should be included a ThenInclude is required:
var blogs = context.Blogs.Include(b => b.Posts)
.ThenInclude(p => p.Content).ToList();
So if Posts will always be queried through Blogs, owned type may be appropriate.
I don't think this applies here, but it does when children having owned types have an identifying relationship with their parents (classical example: Order-OrderLine).
Table splitting
With table splitting a database table is split up into two or more entities. Or, from the objects side: two or more entities are mapped to one table. The model is almost identical. The only difference is that PostContent now has a required primary key property (ID, of course having the same value as Post.ID):
public class Post
{
public int ID { get; set; }
public Blog Blog { get; set; }
public string Title { get; set; }
public PostContent Content { get; set; }
}
public class PostContent
{
public int ID { get; set; }
public string Content { get; set; }
}
And the table-splitting mapping:
modelBuilder.Entity<Post>()
.HasOne(e => e.Content).WithOne()
// or .WithOne(c => c.Post) if there is a back reference
.HasForeignKey<PostContent>(e => e.ID);
modelBuilder.Entity<Post>().ToTable("Posts");
modelBuilder.Entity<PostContent>().ToTable("Posts");
Now Posts will always be queried without their contents by default. PostContent should always be Include()-ed explicitly.
Also, PostContent can now be queried without its owner Post:
var postContents = context.Set<PostContent>().ToList();
I think this is exactly what you're looking for.
Of course you can do without these mappings if you'll always use projections when you want to fetch posts without contents.
You can try this :
using (var context = new BloggingContext())
{
var blogProps = context.Blogs
.SelectMany(b =>
b.Posts.Select(p =>
new { Blog = b, PostTitle = p.Title }
)
)
.ToList();
}
EDIT
If you want to stick to your data model, you could try something like this :
using (var context = new BloggingContext())
{
var blogProps = context.Blogs
.Select(b =>
new Blog
{
Name = b.Name,
Posts = new List<Post>(b.Posts.Select(p =>
new Post
{
Title = p.Title
})
}
)
.ToList();
}
I think there's a much easier way to do this. Projection is nice and all, but what if you want all the columns from your parent entity and most of them from the child? When those types have a lot of properties, using projection means you have a lot of lines of code to write just to select everything you want except the few that you don't. Well, since using projection means your entities won't be tracked, it's much easier to use .AsNoTracking() and then just empty out the things you don't want.
var foos = await _context.DbSet<Foo>()
.AsQueryable()
.Where(x => x.Id == id)
.Include(x => x.Bars)
.AsNoTracking()
.ToListAsync();
foreach (var foo in foos)
{
foreach (Bar bar in foo.Bars)
{
bar.Baz = null;
}
}
Background
Recently I changed jobs and attached to a Web API project. I am familiar with the concepts of Web API & MVC but have no prior hands-on experince.
I have followed few tutorials and based on them created an empty WebApi project via Visual Studio 2017, hooked up my model from Database and added Controllers.
This is the revised controller:
private MyEntities db = new MyEntities();
//...
[ResponseType(typeof(MyEntityType))]
[Route("api/MyEntity")]
public async Task<IHttpActionResult> GetMyEntityType([FromUri]int parameter)
{
MyEntityType found = db.MyEntity
.OrderByDescending(c => c.CreationTime)
.First(c => c.ParameterColumn == parameter);
if (found == null)
{
return NotFound();
}
return Ok(found );
}
Note : I am querying based on a column other than KEY
When I make a call to .../api/MyEntity?parameter=1 I expect to receive a single item in response. But for reasons unknown to me, the previous call returns all items and it is unsorted.
Please note: If I place a breakpoint on if (found == null), I can confirm that my query has resulted in a single item.
Question
What am I missing here? Why does the response contains all elements instead of single element?
UPDATE 1
I tried the same call from Postman, this is the output. Please note that I have changed the request, controller code etc. in question to omit some private details.
I can see that response contains my desired data, but along with all of inner data in other end of relationship. If I am not mistaken, by default, EF uses lazy loading. Since I have no Include clause, I have no idea why all related data is returned in response.
I think I need to investigate my relationships in Model/DB and make sure Lazy-Loading is enabled.
UPDATE 2
These are my entity classes:
public partial class MyEntity
{
public int Id { get; set; }
public Nullable<int> ForeignKey_ID { get; set; }
public Nullable<int> MyValue { get; set; }
public Nullable<System.DateTime> CreationTime { get; set; }
public Nullable<int> Some_ID { get; set; }
public virtual MyOtherEntity MyOtherEntity { get; set; }
}
public partial class MyOtherEntity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public MyOtherEntity()
{
this.MyOtherEntity1 = new HashSet<MyOtherEntity>();
}
//...
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MyOtherEntity> MyOtherEntity1 { get; set; }
public virtual MyOtherEntity MyOtherEntity2 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MyEntity> MyEntity { get; set; }
}
When the MyEntityType instance is returned via Ok it will be converted to JSON which will read the values of all the public properties and fields. This will cause EF to load the entire entity and all relationships. If you only require specific properties to be returned then use Select() as below.
var found = db.MyEntity
.OrderByDescending(c => c.CreationTime)
.Select(c => new { c.CreationTime, c.ParameterColumn })
.First(c => c.ParameterColumn == parameter);
You can tailor the selected properties as required. If you require criteria in First() that does not need to be selected, move the condition into a Where() call before the Select.
var found = db.MyEntity
.OrderByDescending(c => c.CreationTime)
.Where(c => c.ParameterColumn == parameter)
.Select(c => new { c.CreationTime })
.First();
You should probably create a ViewModel of MyEntityType that has only the properties you require, and map these to a new instance of the ViewModel instead. You can then update the [ResponseType(typeof(MyEntityType))] attribute too.
For example, declare:
public class MyEntityTypeViewModel {
public DateTime CreationTime { get; set; }
public int ParameterColumn { get; set; }
}
And then in your controller action:
MyEntityTypeViewModel found = db.MyEntity
.OrderByDescending(c => c.CreationTime)
.Where(c => c.ParameterColumn == parameter)
.Select(c => new MyEntityTypeViewModel {
CreationTime = c.CreationTime,
ParameterColumn = c.ParameterColumn })
.First();
If you're using Entity Framework Core 2, try this:
MyEntityType found = await db.MyEntity.AsNoTracking()
.OrderByDescending(c => c.CreationTime)
.FirstOrDefaultAsync(c => c.ParameterColumn == parameter);
And it's better to include database context via Dependency Injection, not with private field.