Having issues passing Objects among tiers - c#

I'm trying to do something that should be real simple but I'm getting errors I don't know how to correct. Also, I don't even know if I'm doing things the "correct" way.
I have 3 entities. My first entity is called Bill and it's my main one. The other two are Repeat and Type. Bill has foreign keys (i.e. TypeId) which point to their respective primary keys. Both Type and Repeat are similar. They have their Id and description.
What I'm trying to do with EF and LINQ to Entity: Get all bills with all the properties of Bill but instead of the TypeId, I want TypeDesc.
This is an N tier Solution with 3 projects
Thus far I have my data layer I call Model, business layer I call BLL and my presentation later I call GUI.
namespace BillApp.Model
{
public class BillModel
{
public List<BillType> GetAllBills()
{
using (BillsEntities be = new BillsEntities())
{
var results = from o in be.Bills
.Include("Type")
.Include("Repeat")
select new
{
BillId = o.BillId,
Name = o.Name,
URL = o.URL,
PaymentAmount = o.PaymentAmount,
Balance = o.Balance,
DueDate = o.DueDate,
TypeDesc = o.Type.TypeDesc,
RepeatDesc = o.Repeat.RepeatDesc,
Username = o.UserName
};
return results.ToList();
}
}
}
public class BillType
{
#region Properties
public int BillId { get; set; }
public string Name { get; set; }
public string URL { get; set; }
public decimal PaymentAmount { get; set; }
public decimal Balance { get; set; }
public DateTime DueDate { get; set; }
public string TypeDesc { get; set; }
public string RepeatDesc { get; set; }
public string Username { get; set; }
#endregion
}
}
results returns an error Cannot implicitly convert type System.Linq.IQueryable<AnonymousType#1> to System.Collections.Generic.List<BillApp.Model.BillType>
Next I try and pass the object to my BLL with this code.
namespace BillApp.BLL
{
public class BillBLL
{
public List<BillType> GetAllBills()
{
BillModel b = new BillModel();
return b.GetAllBills();
}
}
}
But BillType has an error:The type or namespace name 'BillType' could not be found (are you missing a using directive or an assembly reference?)
What am I missing? What can I do better?

I think the error messages are pretty clear: results is of type IQueryable<T> and you're trying to return a List<T>. To return a list instead, you can use the ToList method. You'll also need to create instances of BillType instead of anonymous objects, so that it conforms to the List<BillType> return type. Your GetAllBills method would look like this:
public List<BillType> GetAllBills()
{
using (BillsEntities be = new BillsEntities())
{
var results = from o in be.Bills
.Include("Type")
.Include("Repeat")
select new BillType
{
BillId = o.BillId,
Name = o.Name,
URL = o.URL,
PaymentAmount = o.PaymentAmount,
Balance = o.Balance,
DueDate = o.DueDate,
TypeDesc = o.Type.TypeDesc,
RepeatDesc = o.Repeat.RepeatDesc,
Username = o.UserName
};
return results.ToList();
}
}
For the second error you're probably just missing a using directive to have access to your BillType type which is in a different namespace. You'd have this line at the top of the file:
using BillApp.Model;

Related

Map List of one Type to a list of another similar Type

I have two different classes:
The following is a model for the database table named "Attachments":
namespace WebApi.Models
{
public class Attachment
{
public enum EntityType
{
Transaction
}
public int AttachmentId { get; set; }
public int EntityId { get; set; }
public EntityType Type { get; set; }
public string Filename { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
}
}
and in my dbContext class I have something like the following:
namespace WebApi.Models
{
public class accountingContext : DbContext
{
public DbSet<User>? Users { get; set; }
public DbSet<Transaction>? Transactions { get; set; }
public DbSet<Attachment>? Attachments { get; set; }
///...
}
}
and then I have a similar cvlass to the Attachement model which is usedf to send data back in response to a web api request, the class is below:
namespace WebApi.Entities.AttachmentResponse;
public class AttachmentResponse
{
public int AttachmentId { get; set }
public string Filename { get; set; }
}
I wish to keep my class for responses seperate rather then using the model classes for reasons I don't feel worthwhile going into.
After performing a query against the model classes I need to convert the result and map to the AttachmentResponse class. I am trying the following:
List<WebApi.Entities.AttachmentResponse> attachments = (
from a in db.Attachments
from t in db.Transactions.Where(t => a.EntityId == t.TransactionId && t.UserId == userId)
where a.EntityId == EntityId
select new
{
a.AttachmentId,
a.Filename
}).ToList();
But I get an error with the above attempt. I have also looked at ConvertAll but cannot see how to use it in the code above.
Is it possible to accomplish what I am attempting? If so, where am I going wrong above?
You're creating a list of an anonymous type, not a list of AttachmentResponse objects. You need to explicitly create them in the projection:
select new AttachmentResponse
{
AttachmentId = a.AttachmentId,
Filename = a.Filename
}
I would also look at tools like AutoMapper that can create mappings very easily, especially when the property names are the same.
I can't comment, so I can't ask what error you're getting. However, from looking at it, it looks like a casting problem. You can cast anonymous types to other types. Using just new makes is anonymous instead specify they type that you are declaring new.
List<WebApi.Entities.AttachmentResponse> attachments = (
from a in db.Attachments
from t in db.Transactions.Where(t => a.EntityId == t.TransactionId && t.UserId == userId)
where a.EntityId == EntityId
select new WebApi.Entities.AttachmentResponse
{
a.AttachmentId,
a.Filename
}).ToList();

C# IQueryableto to IEnumerable using Linq expressions and class

I have a class which should take the query results from a database using a join.
My class is:
`
public class StepTwo
{
public int Id { get; set; }
public string Party { get; set; }
public string Currency { get; set; }
public string Account { get; set; }
public double? Amount { get; set; }
}
`
I have then created a method which will return the results:
public IEnumerable<StageTwo> StepTwo()
{
var queryJoin = (from inn in db.Input.Take(10)
join yacc in db.AccY on inn.Action equals yacc.Action
orderby inn.Id descending
select new
{
inn.Id,
inn.XParty,
inn.Curr,
yacc.Action,
inn.Amount
});
return queryJoin;
}
In other methods where I did not use a join, this worked fine but now it is not working. I have the error message on the return queryJoin; stating:
`
Cannot implicitly convert type 'System.Linq.IQueryable<<anonymous type: int Id, string XParty, string Curr, string YAction, double? Amount>>' to '
System.Collections.Generic.IEnumerable<Project.StepTwo>'. An explicit conversion exists (are you missing a cast?)`
I know the class names are a bit different from the database names but I have tried to change them to match. Based on the error above, I assume it's something else.
Any advise would be appreciated, thank you.
Your error message is telling you that queryJoin is an anonymous type, but you are trying to force it to be an IEnumerable<StageTwo>, and C# can't make that conversion.
The reason queryJoin is an anonymous type is because you've not defined it in your linq query. So to fix it, instead of this:
select new
{
inn.Id,
inn.XParty,
inn.Curr,
yacc.Action,
inn.Amount
});
You'd want this:
select new StepTwo
{
Id = inn.Id,
Party = inn.XParty,
Currency = inn.Curr,
Account = yacc.Action,
Amount = inn.Amount
});

Entity framework cannot seem to create relationship

The entity framework isn't super new to me, however is confusing as I continue to expand my data models. I am attempting to create a class that has an array of another class. Class A or County.cs has a list of Class B or Product.cs
I cannot seem to create write these classes in a way that when you ask for context.counties you also get the array of products attached to it.
Class A or County.cs
public class County
{
[Key]
public int ID { get; set; }
public String Name { get; set; }
public List<Product> Products { get; set; } = new List<Product>();
[NotMapped]
public DateTime firstAppearance {
get {
var data = (from obj in Products orderby obj.Date descending select obj.Date).FirstOrDefault();
if (this.softwareIn)
{
return data;
}
else
{
var date = new DateTime(1,1,1);
return date;
}
}
set {
this.firstAppearance = value;
}
}
[NotMapped]
public bool softwareIn {
get {
return Products.Count() >= 1;
}
set {
this.softwareIn = value;
}
}
}
Class B or Product.cs
public class Product
{
[Key]
public int ID { get; set; }
public String Name { get; set; }
public DateTime Date { get; set; }
[NotMapped]
public DateTime DateUtc {
get {
return getUtcDate();
}
set {
this.DateUtc = value;
}
}
public DateTime getUtcDate() {
return this.Date.ToUniversalTime();
}
}
I just don't understand and haven't created enough of 1:M relations in the entity framework. Why cannot I do something like this and have it work all the time? The first time I run this I get the type of data I expect, the xx county has a product. However if I remove all this and just return the context.counties I get nothing in the products array.
[Route("Counties")]
public object GetCounties() {
var data = new County() {
Name = "xxx",
};
data.Products.Add(new Product() { Name="Cool Software", Date = DateTime.Now});
db.Counties.Add(data);
db.SaveChanges();
var da = db.Counties.ToList();
return db.Counties;
}
The reason you have having this issue is because the foreign keys are not correctly configured. Take a look at your database and look at the foreign keys. For Entity Framework to understand the relationships properly, you must mark related entities as virtual. So do this:
public virtual List<Product> Products { get; set;}
And then in your Product class add the navigation property back to the parent County:
public virtual County County { get; set;}
I found this tutorial really good:
http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
Hope this helps.

Generic to Specific list returns "Cannot cast error" in c#

I am using .NET 4.6 and I am trying to create a specific list from a generic one. Code(the generic list):`
var clients = (from a in accounts
group j by new
{
a.Code,
a.Name,
a.AddressLine1,
a.Postcode,
a.City,
}
into g
select new
{
g.Key.Code,
g.Key.Name,
g.Key.AddressLine1,
g.Key.PowerTools,
g.Key.Internetportal,
g.Key.Huisvestingsplanning,
g.Key.Werkplanning,
g.Key.Vervoersplanning
}).ToList();
The specific List(Customer.cs):
struct Customer
{
public string Code { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public double PowerTools { get; set; }
public double Internetportal { get; set; }
public double Huisvestingsplanning { get; set; }
public double Werkplanning { get; set; }
public double Vervoersplanning { get; set; }
}
Conversion:
customers = clients.Cast<List<object>>().Select(x => new Customer(){
Code = (string)x[0],
Name = (string)x[1],
Address = (string)x[2],
PowerTools = (double)x[3],
Internetportal = (double)x[4],
Huisvestingsplanning = (double)x[5],
Werkplanning = (double)x[6],
Vervoersplanning = (double)x[7]}).ToList();
The error this conversion throws:
Unable to cast object of type '<>f__AnonymousType68 [System.String,System.String,System.String,System.Double,System.Double,System.Double,System.Double,System.Double]' to type 'System.Collections.Generic.List1[System.Object]'.
Thanks
Your code appears to be trying to convert some object into a list of its properties - this isn't going to work, C# isn't JavaScript. It's doable, but completely unnecessary.
What you really need is to just use the anonymous type in the way it's meant to be used:
clients.Select(x => new Customer { Code = x.Code, Name = x.Name, ... }).ToList();
Depending on the actual LINQ provider you're using, it might even be possible to skip the middle man and select directly into your own type - consult the documentation.
Also, just for clarity - both of those lists are generic. The difference is that the first one is a generic list of an anonymous type, while the second one is a generic list of a named type.

C# - The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

I'm sorry for the repetition. I'm heading with a same problem but still could not handle it. I'm using Angularjs framework and Asp.net mvc.
My person class:
public partial class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Telephone { get; set; }
public string Adress { get; set; }
public int UserID { get; set; }
public virtual User User { get; set; }
}
My User class:
public partial class User
{
public User()
{
this.People = new HashSet<Person>();
}
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string Gender { get; set; }
public virtual ICollection<Person> People { get; set; }
}
My js code:
$http.get('/Data/GetPeople', { params: { UserID: "1" } }).success(function (data) {
$scope.model = data;
});
I'm trying to get records from my database:
public ActionResult GetPeople(int UserID)
{
using (PersonEntities dc = new PersonEntities())
{
var model = new PersonIndexVM();
model.People = dc.People.Where(b => b.UserID == UserID).ToList();
//model.People = dc.People.Include("User").ToList();
return Json(model, JsonRequestBehavior.AllowGet);
}
}
As I see with debugging, I'm getting the right objects from database in GetPeople method. But after that I'm getting this error:
'The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.'
I tried to Eagerly load: model.People = dc.People.Include("User").Where(b => b.UserID == UserID).ToList(); Still getting the same error.
It would be a pleasure if you help me.
The problem is solved. I get help from my friend. Its about unclosed connection. Its my fault. I didn't mention it.
In PersonIndexVM(), I created People = new List<Person>(); Person class is created by entity framework. It is related with database. When I create a model that is an object of PersonIndexVM() in GetPeople() method and return this model object as a json, model object try to reach User class informations after the connection closed. And I'm getting this error. To solve this problem:
Closing the lazy loading to prevent reaching User information. dc.Configuration.LazyLoadingEnabled = false;
Creating another class not related with database and return its object as Json.
You can strongly type your inclusion, which will give you hints as to whether or not your object structure is correctly related. This solves any "magic strings" issues, such as your table being named Users instead of User inside of your EF context, after including DbExtension.
using System.Data.Entity.DbExtension;
model.People = dc.People.Include(c => c.User).ToList();
However, if you are using ObjectContext instead of DbContext, you may be stuck with magic strings. That said, EF will "pluralize" most names, so your table is most likely named "Users". Check to see if the table exists as dc.Users and, if it does, change your magic string to match.
model.People = dc.People.Include("Users").ToList();
It's look like the problem is when you using keyword Using.
Look at this How to solve the error The ObjectContext
In my case, i was passsing all model 'Users' to a column, and it doesn't mapped correctly, so i just pass 'Users.Name' and it fixed it.!!
var data = db.ApplicationTranceLogs
.Include(q=>q.Users).Include(q => q.LookupItems)
.Select(q => new { Id = q.Id, FormatDate = q.Date.ToString("yyyy/MM/dd"), Users = ***q.Users***, ProcessType = q.ProcessType, CoreProcessId = q.CoreProcessId, Data = q.Data })
.ToList();
--
var data = db.ApplicationTranceLogs
.Include(q=>q.Users).Include(q => q.LookupItems)
.Select(q => new { Id = q.Id, FormatDate = q.Date.ToString("yyyy/MM/dd"), Users = ***q.Users.Name***, ProcessType = q.ProcessType, CoreProcessId = q.CoreProcessId, Data = q.Data })
.ToList();
In my case I had a bug in the front end, which was causing the same function in the backend to be triggered 3 times, causing a threading issue.
Maybe look into this as a possibility too.

Categories

Resources