Getting Specific Columns in Entity Framework - c#

I would like to get the list of users from the database, but I want only 5 columns instead of all (it has about 35 columns). When I wrote like the following, it shows me no error at the compile time but the error at the runtime.
bksb_Users is the table name in my database as well as object name in the Entity Model.
public List<bksb_Users> SearchStudents(string reference, string firstname, string lastname)
{
return (from u in context.bksb_Users
where u.userName.Contains(reference)
&& u.FirstName.Contains(firstname)
&& u.LastName.Contains(lastname)
orderby u.FirstName, u.LastName
select new bksb_Users
{
user_id = u.user_id,
userName = u.userName,
FirstName = u.FirstName,
LastName = u.LastName,
DOB = u.DOB
}).Take(100).ToList<bksb_Users>();
}
The error is...
The entity or complex type 'bksbModel.bksb_Users' cannot be constructed in a LINQ to Entities query.

Does below work?
public List<bksb_Users> SearchStudents(string reference, string firstname, string lastname)
{
var anon = (from u in context.bksb_Users
where u.userName.Contains(reference)
&& u.FirstName.Contains(firstname)
&& u.LastName.Contains(lastname)
orderby u.FirstName, u.LastName
select new
{
user_id = u.user_id,
userName = u.userName,
FirstName = u.FirstName,
LastName = u.LastName,
DOB = u.DOB
}).Take(100).ToList();
return anon.Select(z => new bksb_Users()
{
user_id = z.user_id, userName = z.userName, FirstName = z.FirstName, DOB = z.DOB
}).ToList();
}
All I have done is split the task into two steps:
Get the data out (into an anonymous type) using LINQ to Entities.
Convert the anonymous type into the desired type using LINQ to
Objects.
Note a better option would be to create a new type (class) that contains just the fields/properties you need - that would remove the need for step 2, and will make it clear to the callers of your function which columns are 'populated' and which aren't. It also means you are less likely to 'accidentally' try and persist these half populated entities back to the database.

for some reason i quess that field DOB looks something like this
public object DOB { get { return fieldX + fieldY } }
Entity framework does not understand that. All fields in query must be mapped with certain columns in DB

Related

Query Entity Framework using C# and Navigation Properties

First of all I am new to both C# and EF.
I have created a number of entities with the the Model designer in VS 2015 CE and set the relationships.
I would like to query the entities to return all the customers for a specific Contract (e.g. Contract_ID = 1), along with related properties from the CustomerLocker and ContractCustomer entities (For the CustomerLocker Entity if they are present, or null if they are not). I also have the LockerNumber value from the Contract entity (e.g. 100).
I would be grateful if someone can help with the LINQ query required to select the properties I require. I would prefer to be able to use navigation properties if possible.
So far I am able to select the customers but not able to select properties from the CustomerLocker entity.
var myCustomers = (from cc in context.ContractCustomers
where cc.Contract_ID.Equals(contractID)
select new
{
Licencee = cc.IsLicencee,
Added = cc.AddedDate,
Firstname = cc.Customer.FirstName,
Lastname = cc.Customer.LastName,
DOB = cc.Customer.DateOfBirth,
Postcode = cc.Customer.PostCode,
CustomerNumber = cc.CustomerNumber
}
)
entities shown in VS Model Designer
You could get the HasCard from CustomerLockers by filtering on LockerNumber;
CustomerLockers = cc.Customer.CustomerLockers
The query;
var myCustomers = (from cc in context.ContractCustomers
where cc.Contract_ID.Equals(contractID)
select new
{
Licencee = cc.IsLicencee,
Added = cc.AddedDate,
Firstname = cc.Customer.FirstName,
Lastname = cc.Customer.LastName,
DOB = cc.Customer.DateOfBirth,
Postcode = cc.Customer.PostCode,
CustomerNumber = cc.CustomerNumber,
CustomerLockerHasCard = cc.Customer.CustomerLockers
.Where(x => x.LockerNumber == 1000)
.Select(x => x.HasCard)
}
)
Also, I suggest you to define model classes as known type instead of using anonymous type.
An option would be to get the list of customers instead of just the customer's number :
var myCustomers = (from cc in context.ContractCustomers
where cc.Contract_ID.Equals(contractID)
select new
{
Licencee = cc.IsLicencee,
Added = cc.AddedDate,
Firstname = cc.Customer.FirstName,
Lastname = cc.Customer.LastName,
DOB = cc.Customer.DateOfBirth,
Postcode = cc.Customer.PostCode,
CustomerNumber = cc.CustomerNumber,
listOfCustomers = cc.Customer.ToList() // <-Here, a list
}
)
Then you can use a loop :
foreach(var customer in myCustomers.listOfCustomers)
{
var listOfLockers = customer.CustomerLockers.ToList();
}
But this is more a beginner's way, remember it's always better to take everything you need in a single query, like Stormcloack's answer.
This answer is just to show you how you can dig in the entitys the easy way.

Linq to list, select only four columns from DB?

My table has over 15 columns and I only want to retrieve four of those columns to store in memory. However trying the below method, gives the error cannot explicitly convert List to IEnumerable. Is this also the correct approach? Have a feeling I am missing a where clause or something? CompanyID is the index.
IEnumerable<Company> company = _db.Company.Select(a => new
{
CompanyId = Convert.ToString(a.CompanyId),
CompanyType = a.CompanyType,
CompanyName = a.CompanyName,
Email = a.Email
}).ToList();
You create an Anonymous Type with your Select statement and you can not convert List<definedAnonymousType> to IEnumerable<Company>.
Use var instead of IEnumerable<Company>.
var company = _db.Company.Select(a => new
{
CompanyId = Convert.ToString(a.CompanyId),
CompanyType = a.CompanyType,
CompanyName = a.CompanyName,
Email = a.Email
}).ToList();
then your company type will be List<definedAnonymousType>.
you can create CompanyLite dto with the exact properties you want and convert data to that
var companyLite = _db.Company.Select(a => new CompanyLite
{
CompanyId = Convert.ToString(a.CompanyId),
CompanyType = a.CompanyType,
CompanyName = a.CompanyName,
Email = a.Email
}).ToList();

Can't reference variable from anonymous type

I am grabbing a value and want it to appear in the BatchId of every anonymous type created via a linq statement.
Here is the code:
var batchId = context.Request["batchid"];
using (var db = new StarterSiteEntities())
{ // Get data
var transactions = (from t in db.Transactions
join td in db.TransactionDetails on t.TransactionID equals td.TransactionID
join p in db.Products on td.ProductID equals p.ProductID
where t.Exported == false
select new
{
BatchId = batchId,
t.FirstName,
t.LastName,
t.Address1,
t.Address2,
t.City,
t.State,
t.Zip_Code,
t.Email,
t.Phone,
t.TotalAmount,
t.MonthlyGift,
t.DateCreated,
p.Fund,
ProductFirstName = p.FirstName,
ProductLastName = p.LastName,
ProductUniversity = p.University,
ProductState = p.State,
ProductEmail = p.Email,
ProductAmount = td.Amount
}).ToList();
}
When I do this, I get the error message:
"A parameter is not allowed in this location. Ensure that the '#' sign is in a valid location or that parameters are valid at all in this SQL statement."
How do I reference the batchId variable from within the anonymous type declaration, or should I accomplish this another way?
It looks like you ran into a known bug in the SQL Server CE data access libraries. You should be able to fix it by applying this hotfix to the machine(s) that are accessing the database.
While I think Adam Maras answered my question. Because I did not want to install a hot-fix on the server, I ended up solving the problem using a different method.
Since the Linq query would not allow me to use a string variable and I could not edit the property value of an anonymous type. I stopped using an anonymous type and created an entity class to hold my "transaction summary" data.
Once I have a collection of TransactionSummary objects, I can use the Select() method to update the BatchId property value in each record.
Here is the resulting code:
// Define a custom type to hold the data
private class TransactionSummary
{
public string BatchId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
//...removed lines for brevity...
}
//...here is the updated code snippet...
using (var db = new StarterSiteEntities())
{ // Get data
var transactions = (from t in db.Transactions
join td in db.TransactionDetails on t.TransactionID equals td.TransactionID
join p in db.Products on td.ProductID equals p.ProductID
where t.Exported == false
select new TransactionSummary
{
FirstName = t.FirstName,
LastName = t.LastName,
//...removed lines for brevity...
}).ToList();
// The client would like a batchID added to each record that we return.
var batchId = context.Request["batchid"];
transactions.Select(t => { t.BatchId = batchId; return t; }).ToList();
}

LINQ to Entities - How to retrieve a data and use it as a variable in the whole project

I have 1 WinForm and 2 tables:
Form1 contains TextBox1
Employee contains ID, LastName, FirstName, BirthDate.
Tasks contains ID, TaskName
I need to input LastName and FirtName in TextBox1 to retrieve the related "TaskName" if exists,
then make the retrieved data usable from any location in the project
I need to know where to put the TaskName variable?
and how can I modify the next code to reach that purpose?
using (LINQtoEntitiesEntities MyEntities = new LINQtoEntitiesEntities())
{
ObjectQuery<Employee> Employee = MyEntities.Employee;
var query = (from p in Employee
where p.FirstName == TextBox1.Text.Trim()
select p.LasttName, p.FirstName);
}
If LastName and FirstName are being input (in that order) to TextBox1 then, assuming they are separated by a space or spaces, you can split them up as follows:
string[] items = TextBox1.Text.Trim().Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
string lastName = items[0];
string firstName = items[1];
The second argument to the Split method deals with the possibility that there might be multiple spaces separating the last and first names.
If the ID column is used to link the Employee and Tasks tables, you should then be able to retrieve the related TaskName and place it in a global variable as follows:
// create a class to contain global variables if you don't already have one
static class Global
{
public static string Task {get; set;}
}
// within some method in some other class
// insert above code to get last and first names
using (LINQtoEntitiesEntities MyEntities = new LINQtoEntitiesEntities())
{
ObjectQuery<Employee> Employee = MyEntities.Employee;
ObjectQuery<Tasks> Tasks = MyEntities.Tasks;
Global.Task = (from e in Employee where e.LastName == lastName && e.FirstName == firstName join t in Tasks on e.ID equals t.ID select t.TaskName).FirstOrDefault();
}
// retrieve global variable from elsewhere:
if (Global.Task != null)
{
// do something with Global.Task
}

Selecting specific columns as certain names in LINQ?

I am trying to populate my WebGrid from LINQ to SQL.
It has the following columns:
Username
Email
First Name
Last Name
IsApproved
IsLockedOut
IsOnline
LastActivityDate
LastLoginDate
CreationDate
All of this comes from the User object:
dbc.Users
However everything except First Name and Last Name is an association from aspnet_Membership and aspnet_User which is defined in my LINQ to SQL. How do I set these as the proper column names?
I tried:
var accounts = dbc.Users.Select(User => new User
{
Username => aspnet_Membership.username
}).ToList();
For username but it is not working.
How would I do this?
It would be:
var accounts = dbc.Users.Select(User => new User
{
Username = aspnet_Membership.username
}).ToList();
No => for property assignment, but assuming that's not the case and what you need is to "flatten" the resultset between multiple objects, one way to work around having one entity with multiple tables is to manage this by using an anonymous class:
var accounts = from u dbc.Users
let m = dbc.aspnet_Memberships.First(i => i.ProviderUserKey == u.UserKey)
select new
{
Username = m.username,
FirstName = u.FirstName
}).ToList();
Or, define a view, and add this to your model. This is another way to have a common entity.

Categories

Resources