I am fleshing out my data access layer and have run into my first issue. I am using Entity Framework code first along with some repositories and asp.net web api to surface the data in json format.
I am trying to get data from two different poco’s served up in a get method. The models are these:
public class Freelancer
{
public int ID { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Avatar { get; set; }
public Address FreelancerAddress { get; set; }
public ICollection<Client> Clients { get; set; }
}
and address:
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
and finally the list of Client objects:
public class Client
{
public int ID { get; set; }
public string Name { get; set; }
public Address ClientAddress { get; set; }
public string Logo { get; set; }
public ICollection<Project> Projects { get; set; }
public int FreelancerID { get; set; }
public Freelancer Freelancer { get; set; }
}
In my Api Controller I am trying to do something like this (simplified for this question):
public IEnumerable<Freelancer> Get()
{
var user = Uow.Freelancers.GetFreelancer(1);
var result = from x in user
select new
{
ID = x.ID,
Name = x.LastName,
Address = x.FreelancerAddress.Street
};
return result;
}
The error I get is this:
Cannot implicitly convert type ‘System.Collections.Generic.IEnumerable’
to ‘System.Collections.Generic.IEnumerable’.
An explicit conversion exists (are you missing a cast?)
I can return just the Freelancer object just fine, but in the Json it will show null for address and clients, even though there is related data. Is there a way to get the objects I need using linq, or should I do some kind of re-design of my DAL. I am in the beginning stages so I am looking for a best practice suggestion if you have one.
Additional Info
This is what gets served up from Uow.Freelancer.GetFreelancer(1);
[{"iD":1,"email":"david.stanley.13@gmail.com","password":"password","firstName":"David","lastName":"Stanley","companyName":null,"avatar":null,"freelancerAddress":null,"clients":null}]
GetFreelancer() looks like this:
public IEnumerable<Freelancer> GetFreelancer(int id)
{
IEnumerable<Freelancer> freelancer = (from x in DbSet
select x);
return freelancer;
}
I don’t see any way to use .Reference or .Include, but that may be the right track. I remember doing something like that a few projects ago…
It works!!*
Here is what needed to happen:
I changed the GetFreelancer method to this:
IEnumerable<Freelancer> freelancer = from x in DbSet
.Include("FreelancerAddress")
.Include("Clients")
where x.ID == id
select x;
return freelancer;
Which did not work at first because Freelancer was referencing Client which had a full reference to Freelance, so it tunnelled forever. I removed the reference in Client so it looks like this instead:
public class Client
{
public int ID { get; set; }
public string Name { get; set; }
public Address ClientAddress { get; set; }
public string Logo { get; set; }
public ICollection<Project> Projects { get; set; }
public int FreelancerID { get; set; }
}
And my output is exactly what I needed: A freelancer and his address, with a list of his clients.
I have not tried this code, this is simply off the top of my head based on the supplied code and what I’ve found via Google, but it will hopefully get you pointed in the right direction.
I think the change should be made in the
GetFreeLancermethod (in terms of getting the related tables). I also noticed you weren’t using the supplied id in the query, which means you’re method as is is going to give you all the entries in the table, so I’ve added in a where clause in my example.The basic idea I’m trying to convey here is that you load the Address and the Clients collection when you get the desired Freelancer record. I’m assuming that DbSet is your context, and I’m guessing at the entity names.
Once you have the proper data returning, you should be able to get whatever you need in your controller method.
Like I said, I haven’t tried this code but at least hopefully it will get you going.
I would also suggest getting LINQPad, as it’s a great tool for testing and playing around with LINQ queries.