I have three simple tables - usergroups, staff, and salutations. All have ID, Name/Desc, and Active columns. The Usergroups are also assigned an optional staff ID, and the staff are assigned a non-optional salutation ID. I wish to query these tables to return a complete list of all active usergroups, with their related staff members (is any), and their related salutations.
A working SQL query is as follows:
SELECT grp.ID, grp.Desc, grp.Active, sub.Name, sub.Desc
FROM Tbl_UserGroup AS grp
LEFT JOIN (
SELECT st.ID, st.Name, sal.Desc
FROM PrmTbl_Staff AS st
LEFT JOIN PrmTbl_Salutation AS sal ON st.SalutationID = sal.ID
WHERE 1
) AS sub ON grp.StaffID = sub.ID
WHERE grp.Active = TRUE
ORDER BY grp.ID DESC
I have a ViewModel as follows:
public class StaffUserGroup
{
public int GroupID { get; set; }
public string GroupDesc { get; set; }
public bool GroupActive { get; set; }
public int? StaffID { get; set; }
public string StaffName { get; set; }
public string SalutationName { get; set; }
public List<PrmTbl_Staff> StaffsList { get; set; }
}
And an attempt at a LINQ query:
IEnumerable<Tbl_UserGroup> grpsQuery;
grpsQuery = from grp in db.Tbl_UserGroups
join sub in(
from st in db.PrmTbl_Staffs
join sal in db.PrmTbl_Salutations on st.SalutationID equals sal.ID
select new { StID = st.ID, st.Name, Salt = sal.Desc }
) on grp.StaffID equals sub.StID
where grp.Active = true
orderby grp.ID descending
select new { grp.ID, grp.Desc, grp.Active, sub.Name, sub.Salt, sub.StID };
Which is loaded in my Controller:
var viewModel = grpsQuery.Select(group =>
new StaffUserGroup
{
GroupID = group.GroupID,
GroupDesc = group.GroupDesc,
GroupActive = group.GroupActive,
StaffID = group.StaffID,
StaffName = group.StaffName,
SalutationName = group.SalutationName,
StaffsList = rtrnStaff
}
);
Note that intellisense was flagging identically named columns between the sub query and the main query, so I introduced some aliases. I also wish to pass to the view a dropdown list of all available staff, hence the List in the viewmodel.
I am getting an error on the select call in the LINQ statement: Cannot implicitly convert type 'System.Linq.IQueryable<AnonymousType#4>' to '<...StaffUserGroup> An explicit conversion exists. Are you missing a cast?
I don't know
Why I need a ViewModel when I can just query the data I need directly to the Controller
What the ViewModel class then actually does with the data retrieved from the query - does it filter it? Construct an object from it? From my background in PHP and MySQL, what would be a comparison?
How to query specific columns from a table. I using select new {}, because I'm assuming that's equivalent?
Why the above LINQ statement doesn't work.
I can post Models, Views, or Controllers if needed. Any help and advice is greatly appreciated!
Question 1
Why I need a ViewModel when I can just query the data I need directly to the Controller
A ViewModel is a POCO that you write which defines exactly what a view needs in order to display itself correctly.
For example, Let's suppose you have a page (view) that welcomes a user.
Welcome, Bob. Your last visit was 2013-10-11.
A ViewModel is a simple class that defines exactly the things that the view needs.
The user's name
The user's last visit
Therefore:
public class UserDetailsViewModel
{
public string FirstName { get; set; }
public DateTime LastVisit { get; set; }
}
It's (usually) the controller's responsibility to create the ViewModel, ensure it's populated, give it to the view and finally return the view. The controller doesn't do much else; its responsibilities are limited and the code in an action should be fairly small.
The reason that you do this is because it's good practice. But that's not good enough, let me explain.
It is possible to simply run a query, return an IEnumerable of some domain object (for example a list of users) and give that to a view. This is done in many MVC demos. The problem is it's very limited/restrictive. What happens if you want to change what the view displays later? What happens if the domain model changes slightly? It's easier to manage and change things when they are neatly organised and concerns are separated.
Question 2
What the ViewModel class then actually does with the data retrieved from the query - does it filter it? Construct an object from it? From my background in PHP and MySQL, what would be a comparison?
The ViewModel is a concept that is native (or at least common) to certain architectural patterns such as MVC and MVVM. The ViewModel doesn't really 'do' anything. It doesn't do any logic; it has no methods. It just contains a list of properties (and attributes) which define what a view that is using this ViewModel will need.
There isn't exactly a PHP equivalent because a ViewModel isn't specific to .NET. It's just a concept that is associated with MVC, MVVM and so on. The PHP equivalent would be a PHP MVC ViewModel. Remember that ASP.NET MVC is just an implementation of the MVC pattern. PHP has its own MVC implementations.
Question 3
How to query specific columns from a table. I using select new {}, because I'm assuming that's equivalent?
This depends on how you're doing it. EntityFramework is an object-relational mapper that is often used in ASP.NET MVC applications. In this way, you don't query your underlying storage or columns directly. Instead EF will map the tables and columns to .NET objects and you manipulate those.
I'd recommand you try to stay with dealing with objects, rather than creating anonymous types as you go and trying to grab specific columns. Remember that LINQ isn't SQL. The approach shouldn't be "Query this table, grab these columns, where this clause" but instead should be "From this group of objects, grab the object here, where this clause".
For example:
var query = from user in Users
where user.FirstName == "Bob"
select user;
Question 4
Why the above LINQ statement doesn't work.
As the description says you're trying to give an IEnumerable of StaffUserGroup an IEnumerable of Anonymous. I believe this is because of the way you are selecting things in order to populate your ViewModel. Its hard to fix the code without know more about how things are structured. My recommendation here is go look at how some other people are doing LINQ/EntityFramework in MVC. It just takes a bit of practice until you get comfortable with how things are working.
It seems you may be trying to put items of new type
select new { grp.ID, grp.Desc, grp.Active, sub.Name, sub.Salt, sub.St }
into a collection intended for items of type
IEnumerable<Tbl_UserGroup> grpsQuery;
Related
I have some C# classes which represent database objects, some of which contain one or more other custom objects or enumerables of custom objects. I'm using dapper for queries, and slapper to map to the custom objects. It works great for single object. I can easily grab a parent object with a specific ID from the database, do some inner joins, and map it and all the things it "owns" to my custom objects in C#. Problem comes when I want to do a select over multiple parent-IDs.
Some context, let's say I have a person, that person has a list of hobbies which have an ID and a Description, a list of days they're available which also have an ID and Description, and maybe another custom field such as whether they have or are even willing to be around children which can also boil down to a simple ID and Description. We'll call that last field child status. I'd write a select statement like this:
SELECT
,person.id as Id
,person.first_name as FirstName
,person.last_name as LastName
,hobby.Id as Hobbies_Id
,hobby.Description as Hobbies_Description
,avail.Id as Availabilities_Id
,avail.Description as Availabities_Description
,child.Id as ChildStatus_Id
,child.Description as ChildStatus_Description
FROM
users.users person
JOIN
users.userhobbies uhobby
ON
person.id = uhobby.UserId -- one-to-many with relational table
JOIN
users.avail hobby
ON
uhobby.HobbyId = hobby.Id
JOIN
users.useravailabilities uavail
ON
person.id = uavail.UserId -- one-to-many with relational table
JOIN
users.availabilities avail
ON
uavail.AvailId = avail.Id
JOIN
users.childstatuses child
ON
person.ChildStatusId = child.Id
Then I want this mapped to a user like this:
class User
{
public Guid Id {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public IEnumerable<Hobby> Hobbies {get; set;}
public IEnumerable<Availability> Availabilities {get; set;}
public ChildStatus ChildStatus {get; set;}
}
Since I'm using exact naming conventions and everything here, the query from Dapper and the Automapping work great just like this:
// Using the above sql in a variable
var data = Connection.Query<dynamic>(sql);
var dataReal = Slapper.AutoMapper.MapDynamic<User>(data);
return dataReal;
This works great, but it only ever returns one user. I have a similar method which takes an ID and all of my test users can be retrieved perfectly by passing the ID. I've tried scouring the internet, looking through documentation, and all I found was this: https://github.com/SlapperAutoMapper/Slapper.AutoMapper/issues/57 who seemed to just slip through the cracks. I also tried mapping the dynamic data to various other structures with no luck. Thanks in advance!
Update:
I've come up with a somewhat brutal, "sledgehammer" type solution. I'm not sure if, at this point, I'm forcing myself to use Slapper when there might be a more convenient solution. However, I wanted to ensure anyone in a similar situation might have a chance at making it work. Here's the new C# section:
var data = Connection.Query<dynamic>(sql);
IEnumerable<Guid> Ids = data.Select(row => (Guid)row.id).Distinct();
List<User> results = new List<User>();
foreach (Guid Id in Ids)
{
IEnumerable<dynamic> rows = data.Where(x => { return ((Guid) x.id).Equals(Id); });
User model = (Slapper.AutoMapper.MapDynamic<User>(rows, false) as IEnumerable<User>).FirstOrDefault();
if (model != null)
{
results.Add(model);
}
}
return results;
As you can see, I'm generating a list of unique "primary object" ID's and selecting those rows into their own lists, which I then pass to Slapper. I've passed the "cache = false" parameter to avoid squeezing unrelated data into every object after the first. I could probably get around this by actually keeping the UserHobby/UserAvailability/UserPhoto Ids in place, but I don't like the way that makes my object look. Hopefully this helps someone.
I'm not familiar with Slapper, but I'll show you what I've done with Dapper to construct a complex graph of objects with bi-directional references.
In short, construct a Dictionary or KeyedCollection prior to calling connection.Query<>, then reference it inside the Dapper lambda expression.
This method returns a list of service calls. Each service call is assigned to one technician and one customer. However, a technician may be assigned multiple service calls to multiple customers. And a customer may have multiple technicians on-site.
public ServiceCallResponse GetServiceCallsDapper(ServiceCallRequest Request)
{
var queryParameters = new {statuses = Request.Statuses, createDate = Request.CreateDate};
const string splitOn = "Number,Id"; // Id indicates beginning of second class (Technician). Number indicates begining of third class (Customer).
// Note multiple columns are named "Number". See note below about how Dapper maps columns to class properties.
// Note Dapper supports parameterized queries to protect against SQL injection attacks, including parameterized "where in" clauses.
const string query = #"sql query here..."
ServiceCallResponse response = new ServiceCallResponse(); // Keyed collection properties created in constructor.
using (IDbConnection connection = new SqlConnection("DB connection string here..."))
{
connection.Open();
// Dapper adds a generic method, Query<>, to the IDbConnection interface.
// Query<(1)ServiceCall, (2)Technician, (3)Customer, (4)ServiceCall> means
// construct a (1)ServiceCall, (2)Technician, and (3)Customer class per row, add to an IEnumerable<(4)ServiceCall> collection, and return the collection.
// Query<TFirst, TSecond, TThird, TReturn> expects SQL columns to appear in the same order as the generic types.
// It maps columns to the first class, once it finds a column named "Id" it maps to the second class, etc.
// To split on a column other than "Id", specify a splitOn parameter.
// To split for more than two classes, specify a comma-delimited splitOn parameter.
response.ServiceCalls.AddRange(connection.Query<ServiceCall, Technician, Customer, ServiceCall>(query, (ServiceCall, Technician, Customer) =>
{
// Notice Dapper creates many objects that will be discarded immediately (Technician & Customer parameters to lambda expression).
// The lambda expression sets references to existing objects, so the Dapper-constructed objects will be garbage-collected.
// So this is the cost of using Dapper. We trade unnecessary object construction for simpler code (compared to constructing objects from IDataReader).
// Each row in query results represents a single service call.
// However, rows repeat technician and customer data through joined tables.
// Avoid constructing duplicate technician and customer classes.
// Refer to existing objects in global collections, or add Dapper-mapped objects to global collections.
// This avoid creating duplicate objects to represent same data.
// Newtonsoft JSON serializer preserves object instances from service to client.
Technician technician;
Customer customer;
if (response.Technicians.Contains(Technician.Id))
{
technician = response.Technicians[Technician.Id];
}
else
{
response.Technicians.Add(Technician);
technician = Technician;
}
if (response.Customers.Contains(Customer.Number))
{
customer = response.Customers[Customer.Number];
}
else
{
response.Customers.Add(Customer);
customer = Customer;
}
// Set object associations.
ServiceCall.Technician = technician;
ServiceCall.Customer = customer;
technician.ServiceCalls.Add(ServiceCall);
if (!technician.Customers.Contains(customer))
{
technician.Customers.Add(customer);
}
customer.ServiceCalls.Add(ServiceCall);
if (!customer.Technicians.Contains(technician))
{
customer.Technicians.Add(technician);
}
return ServiceCall;
}, queryParameters, splitOn: splitOn));
}
return response;
}
Using this technique requires you to set PreserveReferencesHandling = true on the JsonSerializer class so object references are preserved on the client-side. Otherwise, Json.NET will construct duplicate objects and technician.Customers.Count will always == 1.
For example, if John Doe is assigned a service call at Acme and another at Contoso, his technician.Customers.Count will equal 1 if you leave PreserveReferencesHandling == false (Json.NET will construct two Technician objects each named John Doe).
So I have an sqlite database with [Raw_Data] and [Names] tables. Raw_Data has 3 fields that hold a reference (foreign key?) to the Names table (requester, worker, and approver).
When I display data (dgvResults is a DataGridView in a Windows Forms application), I want to merge the names into the main table (Raw_Data).
I am using sqlite-net (by praeclarum on guitub) and have this code (only relevant parts shown for brevity):
...
using (var db=new SQLiteConnection(DB_Interop_SQLite.DB_Path, true))
{
this.Users=db.Table<User>().ToList<User>();
this.Records=db.Table<Raw_Data>().ToList<Raw_Data>();
this.Roles=db.Table<Role>().ToList<Role>();
}
var items=
(
from r in this.Records
join requester in this.Users on r.Requester equals requester.ID into group1
from requester in group1.DefaultIfEmpty()
join worker in this.Users on r.Drafter equals worker.ID into group2
from worker in group2.DefaultIfEmpty()
join approver in this.Users on r.Approver equals approver.ID into group3
from approver in group3.DefaultIfEmpty()
select new {
r.ID, r.Project, Requester=requester, r.Task_Code,
r.DT_submitted, r.DT_required, // other fields
Worker=worker, r.DT_completed, // other related fields
Approver=approver, r.DT_approved, // more fields
}
).ToList();
this.dgvResults.DataSource=items;
...
I have read through LINQ Join 2 List<T>s and Create Items from 3 collections using Linq and Merge multiple Lists into one List with LINQ
They have been a great help.
I also referred to A generic list of anonymous class, which really helped me create the linq query and it all works beautifully.
In my code, User class has ToString() method overwritten so it displays the full name just as I want.
Suppose I wanted a List that holds fields from Raw_Data, but instead of the integer field that refers to the ID from Names, I want the User object as a field, which will hold the ID as well as the rest of the user information (Name, email, phone, etc), just like I have in my anonymous type in the select statement.
So my question is: is there a better way to implement a list (that is not of the anonymous type), without rewriting the entire Raw_Data class just to have a "user" field (from Names table) rather than just the user id?
Ideally, I want the exact same behaviour as my code, but preferably without the anonymous type.
Thanks.
Not sure if this what you're looking for, but you could specify a class just to hold that data, then select into that instead of an anonymous type:
public class RawDataInfo
{
public int ID { get; set; }
public string Requester { get; set; }
...
}
then alter your select RawDataInfo()
select new RawDataInfo(){
ID = r.ID,
Requester = requester,
...
}
You may want to look into something like AutoMapper. This is a library that allows you to easily and consistently map from one type of object to another. It's clean and well tested.
I don't know Linq2Sql so well yet and I was wondering if there is a trick for this probably common MVVM scenario. I have Linq2Sql data context containing Domain models, but I am fetching data for my customized ViewModel object from it.
var query = from ord in ctx.Table_Orders
select new OrderViewModel()
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
};
So i want my ViewModel to inculde both CurrencyId from domain object and the CurrencyText from related table to show it nicely in the View.
This code works great. It generates one DB call with join to fetch the CurrencyText. But the model is simplified, real one has many more fields. I want to make the code reusable because I have many different queries, that returns the same ViewModel. Now every minor change to OrderViewModel requires lots of maintainance.
So I moved the code to OrderViewModel itself as a constructor.
public OrderViewModel(Table_Order ord)
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
}
And call it like this.
var query = from ord in ctx.Table_Orders
select new OrderViewModel(ord);
The Problem: The join is gone DB query is no more optimised. Now I get 1+N calls to database to fetch CurrencyText for every line.
Any comments are welcome. Maybe I have missed different great approach.
This is how far i could get on my own, to get the code reusability. I created a function that does the job and has multiple parameters. Then I need to explicitly pass it everything that has crossed the line of entity.
var query = ctx.Table_Orders.Select(m =>
newOrderViewModel(m, m.Currency.CurrencyText));
The DB call is again optimized. But it still does not feel like I am there yet! What tricks do You know for this case?
EDIT : The final solution
Thanks to a hint by #Muhammad Adeel Zahid I arrived at this solution.
I created an extension for IQueryable
public static class Mappers
{
public static IEnumerable<OrderViewModel> OrderViewModels(this IQueryable<Table_Order> q)
{
return from ord in q
select new OrderViewModel()
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
};
}
}
Now i can do this to get all list
var orders = ctx.Table_Order.OrderViewModels().ToList();
or this to get a single item, or anything in between with Where(x => ..)
var order = ctx.Table_Order
.Where(x => x.OrderId == id).OrderViewModels().SingleOrDefault();
And that completely solves this question. The SQL generated is perfect and the code to translate objects is reusable. Approach like this should work with both LINQ to SQL and LINQ to Entities. (Not tested with the latter) Thank You again #Muhammad Adeel Zahid
Whenever we query the database, we mostly require either enumeration of objects (more than one records in db) or we want a single entity (one record in db). you can write your mapping code in method that returns enumeration for whole table like
public IEnumerable<OrderViewModel> GetAllOrders()
{
return from ord in ctx.Table_Orders
select new OrderViewModel()
{
OrderId = ord.OrderId,
OrderSum = ord.OrderSum,
OrderCurrencyId = ord.OrderCurrencyId,
OrderCurrencyView = ord.Currency.CurrencyText
};
}
Now you may want to filter these records and return another enumeration for example on currencyID
public IEnumerable<OrderViewModel> GetOrdersByCurrency(int CurrencyID)
{
return GetAllOrders().Where(x=>x.CurrencyId == CurrencyID);
}
Now you may also want to find single record out of all these view models
public OrderViewModel GetOrder(int OrderID)
{
return GetAllOrders().SingleOrDefault(x=>x.OrderId == OrderID);
}
The beauty of IEnumerable is that it keeps adding conditions to query and does not execute it until it is needed. so your whole table will not be loaded unless you really want it and you have kept your code in single place. Now if there are any changes in ViewModel Mapping or in query itself, it has to be done in GetAllOrders() method, rest of code will stay unchanged
You can avoid the N+1 queries problem by having Linq2SQL eagerly load the referenced entites you need to construct your viewmodels. This way you can build one list of objects (and some referenced objects) and use it to construct everything. Have a look at this blog post.
One word of warning though: This technique (setting LoadOptions for the Linq2SQL data context) can only be done once per data context. If you need to perform a second query with a different eager loading configuration, you must re-initalize your data context. I automated this with a simple wrapper class around my context.
I'm running into a common need in my project to return collections of my model objects, plus a count of certain types of children within each, but I don't know if it is possible or how to model a "TotalCount" property in a Model class and populate it as part of on single Entity Framework query, preferably using LINQ queries. Is it possible to do this whilst being able to use the Entity Framework .Include("Object") and .Skip() and .Take()? I'm new to the Entity Framework so I may be missing tons of obvious stuff that can allow this...
I would like to be able to paginate on the dynamically constructed count properties as well. I'm thinking that the most scalable approach would be to store the counts as separate database properties and then simply query the count properties. But for cases where there are small row counts that I'm dealing with, I'd rather do the counts dynamically.
In a model like this:
Table: Class
Table: Professor
Table: Attendee
Table: ClassComment
I'd like to return a list of Class objects in the form of List, but I would also like the counts of Attendees and Class comments to be determined in a single query (LINQ preferred) and set in two Class properties called AttendeeCount and ClassCommentCount.
I have this thus far:
var query = from u in context.Classes
orderby tl.Name
select u;
List<Class> topics = ((ObjectQuery<Class>)query)
.Include("ClassComments")
.Skip(startRecord).Take(recordsToReturn).ToList();
Any suggestions or alternative query approaches that can still allow the use of .Include() and pagination would be much much appreciated, in order to produce a single database query, if at all possible. Thank you for any suggestions!
Try this:
public class ClassViewModel {
public Class Class { get; set; }
public int AttendeeCount { get; set; }
public int ClassCommentCount { get; set; }
}
var viewModel = context.Classes.Select(clas =>
new ClassViewModel {
Class = clas,
AttendeeCount = clas.ClassAttendes.Count,
ClassCommentCount = clas.ClassComments.Count}
).OrderBy(model => model.ClassCommentCount).Skip(startRecord).Take(recordsToReturn).ToList();
You don't have to include comments to get count.
It will not work this way. The easiest approach is to use projection into anonymous (or custom) non entity type. I would try something like this:
var query = context.Classes
.Include("ClassComments") // Only add this if you want eager loading of all realted comments
.OrderBy(c => c.Name)
.Skip(startRecord)
.Take(recordsToReturn)
.Select(c => new
{
Class = c,
AttendeeCount = c.Attendees.Count(),
ClassCommentCount = c.ClassComments.Count() // Not needed because you are loading all Class comments so you can call Count on loaded collection
});
The problem in your requirement are AttendeeCount and ClassCommentCount properties. You can't easily add them to your model because there is no corresponding column in database (unless you define one and in such case you don't need to manually count records). You can define them in partial Class implementation but in such case you can't use them in Linq-to-entities query.
The only way to map this in EF is to use DB view and create special read only entity to represent it in your applicaiton or to use DefiningQuery which is custom SQL command defined in SSDL instead of DB table or view.
I've just started learning how to use the Entity Framework to write a very simple C# network monitoring program - this is a learning exercise to try and "drive home" what I've only read about to date. I'm also new to C# and LINQ (just to complicate things further.)
I believe I have the data model suitably normalised but I may be wrong. Visual Studio generates a conceptual model that looks OK. I've pluralised the associations and EntitySets where necessary, but I'm struggling to perform what I think is a fairly basic query/projection on the data.
The database contains 3 tables:
[Server] - A server defined by the user that should be pinged.
ServerID - primary key
HostAddress - IP or hostname
[Result] - A result containing data about the last server test
ResultID - primary key
ServerID - foreign key on [Server].[ServerID]
StateID - an integer used to lookup one of 3 possible Server states
TimeStamp - Time stamp of last ping
[State] - A lookup table containing an integer -> string mapping.
StateID - a unique key
StateLabel - human-readable string like "unreachable" or "OK" or "timeout"
I have manually populated the database using a few simple entries - just enough to give me something to work with.
For starters, I would like to present all of the Result data in a ListView on a WinForm. The ListView contains the following static columns:
State | Server Address | Last checked
In theory, the ListView's data needs to be generated by projecting(?) across each of the 3 tables:
The "State" column should display the human-readable [State].[StateLabel] linked from [Result].[StateID]
The "Server Address" column should display [Server].[HostAddress] linked from [Result].[ServerID]
The "Last Checked" column should display [Result].[TimeStamp]
Since I have no need for the object materialisation and/or change-tracking features of ObjectServices, am I correct in thinking it would be more efficient/correct to use Entity SQL/EntityClient and DbDataReader? If so, what would a suitable Entity SQL query look like?
For what it's worth, I tried using LINQ to Entities and anonymous types in a method but was thwarted by a lack of understanding on a suitable return type:
var results = from r in _context.Result
select new
{
State = (from s in _context.State
where s.StateId == r.StateId
select s.StateLabel),
r.ServerReference.Value.HostAddress,
r.TimeStamp
};
return results.ToList(); // <- No can do.
Thanks for your help!
Steve
Well you won't be able to return a list of anonymous types unless you cast them to object and have the signature define the return type as List<object> (or suitable interface). Your other issue is that the subquery for State will actually return an IQueryable instead of a single entry (you can use the First extension method with EF to get the first matching item.) Although if you have the foreign key relationship the model should have setup an navigation property for the state as well and you should be able to use the property attached instead of a subquery. So if you would like to have this as a method call that returns a list of objects you will have to create a type that represents the transform or downcast to object. Otherwise you could do it at the form level (this all depends on your needs) where you are attempting to bind the list.
public List<object> GetStuff()
{
var results = from r in _context.Result
select new
{
State = r.StateNavigationProperty.StateLabel, //If FK
State = _context.State.First(state => state.StateId == r.StateId), //If Not FK
HostAddress = r.ServerReference.Value.HostAddress,
TimeStamp = r.TimeStamp
};
return results.Cast<object>().ToList();
}
...
myListView.DataSource = GetStuff();
And like I said the other alternative is to either create a class for the transform or bind the list directly to the query.
public class SimpleStuff
{
public string State { get; set; }
public string HostAddress { get; set; }
public DateTime TimeStamp { get; set; }
}
Then just add the class to the select new ala select new SimpleStuff and change the method signature to reflect the class and remove the cast in the return.