简体   繁体   中英

Using LINQ and Entity Framework, how can I just populate some properties of a Dbo with data from the DB?

Title might be confusing, so let me explain. Let's pretend I have a Dbo that looks like this:

public class EmployeeDbo
{
    public int EmployeeId { get; set; }
    public string FirstName{ get; set; }
    public string LastName{ get; set; }
    public string EmployeeData { get; set; }
    public string EvenMoreEmployeeData{ get; set; }
}

And then somewhere in my data access layer I have this code:

  // employeeId is some param that gets passed into this method
  var query = _dbContext.Employees.Where(e => e.EmployeeId = employeeId);

  // Now I want to further modify the query. I just want to load SOME values from the DB, instead of all of them
  // The problem I have is that now this is trying to assign query, which is IQueryable<EmployeeDbo> to IQueryable<{string FirstName, string LastName}>
  query = query.Select(e => new 
      {
          e.FirstName,
          e.LastName
      });

 // More code here that is expecting IQueryable<EmployeeDbo>

So, to summarize my question, how can I just populate SOME properties in a dbo with data from the DB? I suppose I could create a new Dbo with only the data I want as properties, but can I avoid doing that?

Using Select is a Projection, it does not actually retrieve anything from the database, it just nominates what data you will want, and as such it should be moved to the end of your querying to avoid issues /w type.

If you just want to extract a sub-set of names from the query as it is at a particular point then you can use:

var results = query.Select(e => new 
  {
      e.FirstName,
      e.LastName
  }).ToList();

ToList() is actually what executes the query at that point and returns the results into the "results" variable, leaving the "query" variable to be further refined and ultimately consumed.

Otherwise, if you're only going to want to return these details for a view, you need to move the Select towards the end of the search expression chain. The only thing after a Select will typically be ToList and pagination, ( Skip / Take ) or Single / First etc.

Entity Framework keeps an exclusive control on the queries it generates. The DbSets have this mapping defined for the Entities in the corresponding EDMX file in XML notation.

    <EntityType Name="Table1">
      <Key>
        <PropertyRef Name="Id" />
      </Key>
      <Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
      <Property Name="Column01" Type="int" />
      <Property Name="Column02" Type="int" Nullable="false" />
      <Property Name="Column03" Type="varchar" MaxLength="30" />
      <Property Name="Column04" Type="varchar" MaxLength="10" />
    </EntityType>

New instances created "using query.Select(e => new" and eliminating some fields from the output will simply ignore these entity fields. These fields will still be pulled from the database.

As far as I know there is currently no way to "load SOME values from the DB" using EF context. I would not recommend modifying Entity Classes or EDMX manually as it may have some unforeseen issues.

You can examine the queries Entity Framework generates in Visual Studio output window using the below before running the EF query in Visual Studio.

context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

If you want to limit the data load from Entity Framework then consider using stored procedures instead or use other Micro ORMs such as Dapper for a more fine grained control on your data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM