{"error":"Explicit construction of entity type '###' in query is not allowed."} - c#

I am new to LINQ, and i am getting this error message :
{"error":"Explicit construction of entity type 'Proj.Models.Ad' in
query is not allowed."}
I am using this code to retrieve the data
public ActionResult favads()
{
bool isValid = false;
string authToken = "";
if (Request["dt"] != null)
authToken = Request["dt"].ToString().Trim();
else
return Content("{\"error\":\"Please send device token parameter 'dt'.\"}", "application/json");
string message = (new CommonFunction()).ValidateToken(authToken, out isValid);
if (isValid)
{
long userID = 0;
if (Request["userID"] != null)
long.TryParse(Request["userID"].ToString().Trim(), out userID);
else
return Content("{\"error\":\"Please send user id parameter 'userID'.\"}", "application/json");
if (userID < 1)
return Content("{\"error\":\"Please select appropriate user to view details.\"}", "application/json");
try
{
var q = from d in db.AdsFavourites.Where(Favtb => Favtb.CreatedBy.Equals(userID) && Favtb.StatusID.Equals(1)).Select(p => new Ad() { ID = p.AdID.Value, CategoryID = int.Parse(p.CategoryID.ToString()) })
from c in db.Ads.Where(Adstb => Adstb.ID == d.ID).DefaultIfEmpty()
select new
{
FavId = d.ID,
c.ID,
c.Category.ParentCategoryID,
c.Category.CategoryID,
c.Category.LogoFile,
c.Category.CatName,
c.AdTitle,
AdDescription = (c.AdDescription.Length > 50 ? c.AdDescription.Substring(0, 50) : c.AdDescription),
c.CityID,
c.Price,
c.CreationDate,
c.Photos,
c.VideoUrl,
c.IsMobileVisibile
};
int pg = 0;
if (Request["p"] != null)
int.TryParse(Request["p"], out pg);
string _sortby = "MRF";
if (Request["sortby"] != null)
_sortby = Request["sortby"];
if (_sortby.Equals("OF"))
q = q.OrderBy(ad => ad.CreationDate.Value);
else if (_sortby.Equals("PD"))
q = q.OrderByDescending(ad => ad.Price.Value);
else if (_sortby.Equals("PA"))
q = q.OrderBy(ad => ad.Price.Value);
else
q = q.OrderByDescending(ad => ad.CreationDate.Value);
return Json(q.ToList().Skip(pg * recordsPerPage).Take(recordsPerPage), JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Content("{\"error\":\"" + ex.Message + "\"}", "application/json");
}
}
else
{
return Content("{\"error\":\"" + message + "\"}", "application/json");
}
}
Ads class
public class Ads : Ad
{
public long ID { get; set; }
public string FashionType { get; set; }
public string ForRentSale { get; set; }
public string ForJobHire { get; set; }
public string JobTypeID { get; set; }
}

Ad is also mapped and you cannot project a new instance of it like this in a query. See this question.
What you can do is just create an anonymous type or even better in this case, since in your query you only use the ID of the Ad object retrieve just that:
var q = from d in db.AdsFavourites.Where(Favtb => Favtb.CreatedBy.Equals(userID) &&
Favtb.StatusID.Equals(1))
.Select(p => p.AdID.Value)
from c in db.Ads.Where(Adstb => Adstb.ID == d).DefaultIfEmpty()
select new
{
FavId = d,
c.ID,
c.Category.ParentCategoryID,
/* ... */
};
I recommend you look into Navigation Properties. I think it will make this query look neater
Also maybe look at this option instead of using the Method Syntax for the first table, might be more readable:
var q = from d in db.AdsFavourites
//In this case also no need for `Equals` - you are comparing value types
where d.CreateBy == userID && d.StatusID == 1
from c in db.Ads.Where(Adstb => Adstb.ID == d.AdID.Value).DefaultIfEmpty()
select new
{
FavId = d.AdID.Value,
c.ID,
/* ... */
};

Related

Orderby on left join null value

Following situation:
Table of users
Table of addresses
The user has a single optional reference to the address table (=left join)
The query to fetch the data is:
IQueryable<User> query =
from u in _dbContext.Users
join a in _dbContext.Address on u.AddressId equals a.Id into address
from addresses in address.DefaultIfEmpty()
select new User(u, a);
Now I want to do a sorting on the query based on the municipality of the address
query = query.OrderBy(u => u.Address.Municipality);
The problem is that the Address can be a null value (as the address is optional) and for that reason it is throwing following exception.
NullReferenceException: Object reference not set to an instance of an object.
Is there a way to order on the municipality knowing that it can be null?
Already tried following things with same outcome:
query = query.OrderBy(u => u.Address.Municipality ?? "");
query = query.OrderBy(u => u.Address == null).ThenBy(u => u.Address.Municipality);
You can use
query = query.OrderBy(u => u.Address.Municipality.HasValue);
You can write your comparer like this:
public class One
{
public int A { get; set; }
}
public class Two
{
public string S { get; set; }
}
public class T
{
public One One { get; set; }
public Two Two { get; set; }
}
public class OrderComparer : IComparer<Two>
{
public int Compare(Two x, Two y)
{
if (((x == null) || (x.S == null)) && ((y == null) || (y.S == null)))
return 0;
if ((x == null) || (x.S == null))
return -1;
if ((y == null) || (y.S == null))
return 1;
return x.S.CompareTo(y.S);
}
}
static void Main(string[] args)
{
var collection = new List<T> {
new T{ One = new One{A=1}, Two = new Two{ S="dd" } },
new T{ One = new One{A=5}, Two = null },
new T{ One = new One{A=0}, Two = new Two{ S=null } },
new T{ One = new One{A=6}, Two = new Two{ S="aa" } },
};
var comparer = new OrderComparer();
collection = collection.OrderBy(e => e.Two, comparer).ToList();
}
But in your case you have to write var collection = query.AsEnumerable().OrderBy(x=>x.Address).
Also there is other method:
var result = query.Where(x=>x.Address==null || x.Address.Municipality==null)
.Union(query.Where(x.Address!=null && x.Address.Municipality!=null).OrderBy(x=>x.Address.Municipality));
I create a simple demo and it works well when I add nullable foreign key to the two tables.
Besides, I do not understabd what is select new User(u, a); in your code.
Below is my sample code:
Models:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Address")]
public int? AddressId { get; set; }
public Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string AddressName { get; set; }
public string Municipality { get; set; }
}
Action:
IQueryable<User> query =
from u in _context.Users
join a in _context.Address on u.AddressId equals a.Id into address
from addresses in address.DefaultIfEmpty()
select new User
{
Id = u.Id,
Name = u.Name,
AddressId = u.AddressId,
Address = addresses
};
query = query.OrderBy(u => u.Address.Municipality);

How to Convert Anonymous Type to List <dynamic> using Linq to SQL in C#

I'm new to C# and Linq.
Actually, I want to return anonymous types into list. anonymous types is contain of List, String, and DateTime. I tried with the code as below but its giving an error. please help and tell me what I am missing or suggest how can I achieve this.
//Error:
System.InvalidCastException: Specified cast is not valid..
//Edited C# Linq Code
public List<AuditInfo> GetScanAudit(object Id, DateTime? fromTime, DateTime? toTime, string type = null,
string user = null, Pager pager = null)
{
using (var ctx = new PlantDataContext())
{
var query = from audit in ctx.AuditLog
join ent in ctx.Scans on audit.RecordId equals ent.Id.ToString() into audits
from entaudits in audits.DefaultIfEmpty()
where audit.TypeFullName == "ABCD.DB.Model.Scan"
select new
{
audit,
entaudits
};
if (Id != null)
{
query = query.Where(x => x.audit.RecordId == Id.ToString());
}
if (fromTime.HasValue)
{
var tmp = new DateTimeOffset(fromTime.Value.ToUniversalTime());
query = query.Where(x => x.audit.EventDateUTC >= tmp);
}
if (toTime.HasValue)
{
var tmp = new DateTimeOffset(toTime.Value.ToUniversalTime());
query = query.Where(x => x.audit.EventDateUTC <= tmp);
}
if (!string.IsNullOrEmpty(type))
{
var parseEvent = (EventType)Enum.Parse(typeof(EventType), type);
query = query.Where(x => x.audit.EventType == parseEvent);
}
if (!string.IsNullOrEmpty(user))
{
query = query.Where(x => x.audit.UserName == user);
}
if (pager != null)
{
var totalRecords = query.Count();
pager.TotalRecords = totalRecords;
var data = query.Select(x =>
new AuditInfo
{
x.audit.TypeFullName, //Here Error Occurs
x.audit.UserName,//Here Error Occurs
x.audit.EventType,//Here Error Occurs
x.audit.EventDateUTC,//Here Error Occurs
#LogDetails = x.audit.LogDetails.ToList(), //Here Error Occurs
x.entaudits.Name,
#Description = x.entaudits.Description
})
.OrderByDescending(x => x.EventDateUTC)
.Skip(pager.From)
.Take(pager.PageSize);
try
{
var list1 = data.ToList<AuditInfo>();
}
catch (Exception e)
{
}
var list = data.ToList<AuditInfo>();
pager.RecordCount = list.Count;
return list;
}
else
{
var list = query.Select(x =>
new AuditInfo
{
x.audit.TypeFullName,
x.audit.UserName,
x.audit.EventType,
x.audit.EventDateUTC,
#LogDetails = x.audit.LogDetails.ToList(),
x.entaudits.Name,
#Description = x.entaudits.Description
})
.OrderByDescending(x => x.EventDateUTC)
.ToList<AuditInfo>();
return list;
}
}
}
When I debug the code totalRecords variable showing count 6, but is showing exception with message Specified cast is not valid at this line var list1 = data.ToList();
You have to cast the anonymous objects to dynamic.
To do this with linq you can use Cast<dynamic> linq method:
var list = query.Select(x =>
new
{
x.audit.TypeFullName,
x.audit.UserName,
x.audit.EventType,
x.audit.EventDateUTC,
#LogDetails = x.audit.LogDetails.ToList(),
x.entaudits.Name,
#Description = x.entaudits.Description
})
.OrderByDescending(x => x.EventDateUTC)
.AsEnumerable()
.Cast<dynamic>()
.ToList<dynamic>(); \\ here exception occures
return list;
You can use strongly return type for your method like List<ClassName> instead of List<dynamic>
public List<ClassName> GetScanAudit(object Id, DateTime? fromTime, DateTime? toTime, string type = null, string user = null, Pager pager = null)
{
...
}
Then your query will be
var data = query.Select(x =>
new ClassName
{
TypeFullName = x.audit.TypeFullName,
UserName = x.audit.UserName,
EventType = x.audit.EventType,
EventDateUTC = x.audit.EventDateUTC,
LogDetails = x.audit.LogDetails.ToList(),
Name = x.entaudits.Name,
Description = x.entaudits.Description
})
.OrderByDescending(x => x.EventDateUTC)
.Skip(pager.From)
.Take(pager.PageSize);
var list = data.ToList<ClassName>();
And your strongly type class look like
public class ClassName
{
public string TypeFullName { get; set; }
public string UserName { get; set; }
public string EventType { get; set; }
public DateTime EventDateUTC { get; set; }
public List<LogDetail> LogDetails { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Make sure the datatype of each property should match in your .Select clause in query
Edit:
if (pager != null)
{
var totalRecords = query.Count();
pager.TotalRecords = totalRecords;
var data = query.Select(x =>
new AuditInfo
{
TypeFullName = x.audit.TypeFullName,
UserName = x.audit.UserName,
EventType = x.audit.EventType,
EventDateUTC = x.audit.EventDateUTC,
LogDetails = x.audit.LogDetails.ToList(),
Name = x.entaudits.Name,
Description = x.entaudits.Description
})
.OrderByDescending(x => x.EventDateUTC)
.Skip(pager.From)
.Take(pager.PageSize);
try
{
var list1 = data.ToList<AuditInfo>();
}
catch (Exception e)
{
}
var list = data.ToList<AuditInfo>();
pager.RecordCount = list.Count;
return list;
}
else
{
var list = query.Select(x =>
new AuditInfo
{
TypeFullName = x.audit.TypeFullName,
UserName = x.audit.UserName,
EventType = x.audit.EventType,
EventDateUTC = x.audit.EventDateUTC,
LogDetails = x.audit.LogDetails.ToList(),
Name = x.entaudits.Name,
Description = x.entaudits.Description
})
.OrderByDescending(x => x.EventDateUTC)
.ToList<AuditInfo>();
return list;
}

Join (Include) Between Model and AspNetUsers

Several time, i need to get the name of user in AplicationUsers (aspnetusers). Like in Chamado model (table) i have a column Id_Agente (user). With a simple List, i will get something like:
"3q0aju9-9ijuso-9sodkci..."
public class Chamado
{
public int Id { get; set; }
public DateTime Abertura { get; set; }
public string Titulo { get; set; }
public string Descricao { get; set; }
public string Id_Agente { get; set; }
[NotMapped]
public String NomeAgente { get; set; }
}
To work around, I created a NotMapped field and filled it with a foreach:
using (IdentityContext id2 = new IdentityContext())
{
foreach (var item in historicos)
{
item.NomeAgente = id2.Users
.Where(u => u.Id == item.Id_Agente)
.Select(u => u.Nome).FirstOrDefault();
}
}
But now I need to group Chamados by Agente, and it's becoming more and more harder, to work around. I tried to make another notMapped on chamados model named Qtde, make a list and extract from that list but returned a error:
public List<PainelChamados> ListarOrdem()
{
using (SistemaContext db = new SistemaContext())
{
var chamados = db.Chamado
.Where(c => c.Situacao != Chamado.Esituacao.Concluido)
.GroupBy(c => c.Id_Agente)
.Select(c => new Chamado { Id_Agente = c.Key, Qtde = c.Count() });
using (IdentityContext id2 = new IdentityContext())
{
foreach (var item in chamados)
{
item.NomeAgente = id2.Users
.Where(u => u.Id == item.Id_Agente)
.Select(u => u.Nome).FirstOrDefault();
}
}
var query = chamados
.Select(c => new PainelChamados
{
Agente = c.NomeAgente,
Qtde = c.Qtde
});
return query.ToList();
}
}
Last, but not least, how could I just Include aspnetusers table like another regular table:
var query = db.Suporte_Projeto
.Include(l => l.Licenciado)
.Include(c => c.Condominio)
.Include(pr => pr.ProjetoProduto)
.Include(p => p.ProjetoAcesso);
Chart Data
Error
I did another work around! It's seems to be a good option while i cant join aspnetusers to my models table:
public List<PainelChamados> ListarOrdem()
{
using (SistemaContext db = new SistemaContext())
{
var query = db.Chamado
.Where(c => (c.Situacao != Chamado.Esituacao.Concluido && c.Id_Agente != null))
.GroupBy(e => new { e.Id_Agente})
.Select(lg => new PainelChamados
{
CodAgente = lg.Key.Id_Agente,
Qtde = lg.Count()
});
UsuarioData ud = new UsuarioData();
List<PainelChamados> Lista = new List<PainelChamados>();
foreach (var item in query)
{
Lista.Add(new PainelChamados
{
CodAgente = item.CodAgente,
Agente = item.CodAgente == null ? string.Empty : ud.GetAgenteId(item.CodAgente),
Qtde = item.Qtde
});
}
return Lista;
}
}
What do you think, is it the best way to work around? I could return the list i desired.
Chart With Agente Names

Creating a func for better query searching

I am very very new to writing c# using delegates and funcs. Literally watched a pluralsite video an hour ago.
I am trying to write a function that will allow me to write a flexible method for building up a Where clause in my mvc application using EF and IQueryable
To try explain I thought I would write a small example of what I am trying to do as a console application
public static void Main(string[] args)
{
var city1 = new ArgsSearch() {Address = "city1"};
var city2 = new ArgsSearch() { Address = "city2" };
var city1Dealers = DummyDealers().Where(GenerateSearchCriteria<CarDealer>(city1)).ToList();
var city2Dealers = DummyDealers().Where(GenerateSearchCriteria<CarDealer>(city2)).ToList();
foreach (var carDealer in city1Dealers)
{
Console.WriteLine(carDealer.Name);
}
Console.WriteLine("_______________________________________");
foreach (var carDealer in city2Dealers)
{
Console.WriteLine(carDealer.Name);
}
Console.WriteLine("_______________________________________");
}
public static List<CarDealer> DummyDealers()
{
return new List<CarDealer>()
{
new CarDealer() {Address = "city1", Id = 1, Name = "name1"},
new CarDealer() {Address = "city1", Id = 2, Name = "name2"},
new CarDealer() {Address = "city2", Id = 3, Name = "name3"},
new CarDealer() {Address = "city2", Id = 4, Name = "name4"}
};
}
public static Func<TSearch, bool> GenerateSearchCriteria<TSearch>(ArgsSearch args) where TSearch : IBaseModel
{
if (this.GetType() == typeof(CarModel))
{
//return
return e => e.Name == args.Name;// && e.Cost == args.Cost;
}
if (GetType() == typeof(CarDealer))
{
return e => e.Name == args.Name;// && e.Address == args.Address;
}
return e => e.Name==args.Name;
}
public class ArgsSearch
{
public string Name { get; set; }
public string Address { get; set; }
public decimal Cost { get; set; }
}
Am I going down the right track? How do I know that TSearch is either CarModel or CarDealer? allowing my custom search values to be applied.
Thanks for any suggestions and any help would be really appreciated!
You need to cast:
(warning: ugly code ahead)
if (typeof(TSearch) == typeof(CarModel))
{
//return
return e => e.Name == args.Name && ((CarModel)(object)e).Cost == args.Cost;
}
if (typeof(TSearch) == typeof(CarDealer))
{
return e => e.Name == args.Name && ((CarDealer)(object)e).Address == args.Address;
}
return e => e.Name==args.Name;

List based on variable from two tables

My program is a task program of sorts. What I'd like to do is construct a UI for a user/employee to see tasks they have to do on the given day the log in.
I have two tables, PostOne and PostEig, in a 1-M.
PostOne is the master table that contains the information about a single task.
PostEig is a table of users that are assigned to a task in Post One.
The models [simplified]
public class PostOne
{
public string One { get; set; }
[Key]
public string Two { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd-MMM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime ThrD { get; set; }
}
public class PostEig
{
public string EigOne { get; set; }
public string EigTwo { get; set; } //foreign key
[Key]
public string EigID { get; set; }
[Required]
public string EigA { get; set; } //user login
}
I'm having trouble with the controller. I'm not even sure how to start on the code necessary to achieve my goal, so I'm going to try to write it out:
call a list of PostEigs Where EigA == User.Identity.Name
and from this list.. call a list of PostOnes Where Two == EigTwo
and from this list.. call a list of PostOnes Where ThrD == DateTime.UtcNow.Date
I did try something like this:
public ActionResult SkedList()
{
return View(db.PostEigs.Where(m =>
m.EigA == User.Identity.Name ||
m.EigTwo == db.PostOnes.Where(o => o.ThrD == DateTime.UtcNow.Date)
).ToList());
}
If this is unclear, please let me know. I appreciate any advice or solutions, even if in a different direction.
Sounds like this is a candidate for an Inner Join. I find it's much easier to think in terms of SQL then transform it into LINQ.
SQL Query:
SELECT
po.*
FROM
PostOnes po
INNER JOIN
PostEig pe
ON
pe.EigTwo = po.Two
WHERE
pe.EigA = AUTH_NAME AND po.ThrD = TODAY()
C# LINQ Query:
var DB_PostEig = new List<PostEig>()
{
new PostEig(){EigTwo = "Foo1", EigA = "Foo"},
new PostEig(){EigTwo = "Foo2", EigA = "Foo"},
new PostEig(){EigTwo = "Bar1", EigA = "Bar"},
new PostEig(){EigTwo = "Bar2", EigA = "Bar"}
};
var DB_PostOnes = new List<PostOne>()
{
new PostOne(){Two = "Foo1", ThrD = new DateTime(1900,1,1)},
new PostOne(){Two = "Foo2", ThrD = new DateTime(2000,1,1)},
new PostOne(){Two = "Foo3", ThrD = new DateTime(1900,1,1)},
new PostOne(){Two = "Bar1", ThrD = new DateTime(1900,1,1)},
new PostOne(){Two = "Bar2", ThrD = new DateTime(1900,1,1)}
};
var authName = "Foo";
var currentDate = new DateTime(1900,1,1);
//Not sure if this is the most optimal LINQ Query, but it seems to work.
var queryReturn = DB_PostOnes.Join(DB_PostEig.Where(x => x.EigA == authName), x => x.Two, y => y.EigTwo, (x, y) => x)
.Where(z => z.ThrD == currentDate)
.ToList();
queryReturn.ForEach(x => Console.WriteLine(x.Two + " - " + x.ThrD)); //Foo1 - 1/1/1900
Edit:
LINQ Query without a join
var queryTwo = DB_PostOnes
.Where(x => DB_PostEig.Any(y => y.EigTwo == x.Two && y.EigA == authName) && x.ThrD == currentDate)
.ToList();

Categories