Method 'System.String GetState(int32)' has no supported translation to SQL - c#

I'm using the below code to fetch the state. I'm getting the error" Method 'System.String GetState(int32)' has no supported translation to SQL".Please let me know where i'm doing a mistake.
public IQueryable<ViewModel> GetResult()
{
IQueryable<ViewModel> result;
if (isDestinationSite)
{
result = (from table1 in this.db.tblTable1
select new ViewModel
{
State= this.GetState(table1.PersonUID),
});
}
private string GetState(int PersonUID)
{
using ( PersonPref pref = new PersonPref ())
{
pref .selectPref(ApplicationCode.MyApp, PersonPref .preference);
if (pref.PesronValue== "True")
{
return "Successfull";
}
else
{
return "Failure";
}
}
}

SQL doesn't know anything about your function so you just need to move it outside of your linq query.
List<ViewModel> result;
var personUID = (from table1 in this.db.tblTable1 select table1.PersonUID).ToList();
foreach (var id in personUID)
{
result.Add(new ViewModel { State = GetState(id) });
}

You can write iterate your query with AsEnumerable and then do the selection like:
result = (from table1 in this.db.tblTable1
.AsEnumerable()
select new ViewModel
{
State= this.GetState(table1.PersonUID),
});

Related

C# Calculate field inside LINQ Query

I need some help to calculate a property inside my Linq query.
I know I need to use "let" somewhere, but I can't figure it out!
So, first I have this method to get my list from Database:
public BindingList<Builders> GetListBuilders()
{
BindingList<Builders> builderList = new BindingList<Builders>();
var ctx = new IWMJEntities();
var query = (from l in ctx.tblBuilders
select new Builders
{
ID = l.BuilderID,
Projeto = l.NomeProjeto,
Status = l.Status,
DataPedido = l.DataPedido,
DataPendente = l.DataPendente,
DataEntregue = l.DataEntregue,
DataAnulado = l.DataAnulado
});
foreach (var list in query)
builderList.Add(list);
return builderList;
}
Then, I have a function to calculate the Days between Dates accordingly to Status:
public int GetDays()
{
int Dias = 0;
foreach (var record in GetListBuilders)
{
if (record.Status == "Recebido")
{
Dias = GetBusinessDays(record.DataPedido, DateTime.Now);
}
else if (record.Status == "Pendente")
{
Dias = GetBusinessDays(record.DataPedido, (DateTime)record.DataPendente);
}
else if (record.Status == "Entregue")
{
Dias = GetBusinessDays(record.DataPedido, (DateTime)record.DataEntregue);
}
else if (record.Status == "Anulado")
{
Dias = GetBusinessDays(record.DataPedido, (DateTime)record.DataAnulado);
}
}
return Dias;
}
I need to call the GetDays in a DataGridView to give the days for each record.
My big problem is, How do I get this? include it in Linq Query? Calling GetDays() (need to pass the ID from each record to GetDays() function)!?
Any help?
Thanks
I think it would be easier to create an extension method:
public static int GetBusinessDays(this Builders builder) // or type of ctx.tblBuilders if not the same
{
if (builder == null) return 0;
switch(builder.status)
{
case "Recebido": return GetBusinessDays(builder.DataPedido, DateTime.Now);
case "Pendente": return GetBusinessDays(builder.DataPedido, (DateTime)builder.DataPendente);
case "Entregue": return GetBusinessDays(builder.DataPedido, (DateTime)builder.DataEntregue);
case "Anulado": GetBusinessDays(builder.DataPedido, (DateTime)builder.DataAnulado);
default: return 0;
}
}
Then, call it like that:
public BindingList<Builders> GetListBuilders()
{
BindingList<Builders> builderList = new BindingList<Builders>();
var ctx = new IWMJEntities();
var query = (from l in ctx.tblBuilders
select new Builders
{
ID = l.BuilderID,
Projeto = l.NomeProjeto,
Status = l.Status,
DataPedido = l.DataPedido,
DataPendente = l.DataPendente,
DataEntregue = l.DataEntregue,
DataAnulado = l.DataAnulado,
Dias = l.GetBusinessDays()
});
foreach (var list in query)
builderList.Add(list);
return builderList;
}
To do better, to convert a object to a new one, you should create a mapper.
Why does it need to be a part of the query? You can't execute C# code on the database. If you want the calculation to be done at the DB you could create a view.
You're query is executed as soon as the IQueryable is enumerated at the foreach loop. Why not just perform the calculation on each item as they are enumerated and set the property when you are adding each item to the list?

How to sort in LINQ If Join other database

Sort in LINQ
I have 2 database CustomerEntities and BillEntities
I want to get CustomerName from CustomerEntities and sort it but it have no data and I want .ToList() just once time because it slow if used many .ToList()
using (var db1 = new CustomerEntities())
{ using (var db2 = new BillEntities())
{
var CustomerData = db1.Customer.Select(s=> new{s.CustomerCode,s.CustomerName}).ToList();
var BillData = (from t1 in db2.Bill
select new {
BillCode = t1.Billcode,
CustomerCode = t1.Customer,
CustomerName = ""; //have no data
});
}
if(sorting.status==true)
{
BillData= BillData.OrderBy(o=>o.CustomerName); //can't sort because CustomerName have no data
}
var data = BillData .Skip(sorting.start).Take(sorting.length).ToList(); // I want .ToList() just once time because it slow if used many .ToList()
foreach (var b in data)
{
var Customer = CustomerData.FirstOrDefault(f => f.CustomerCode==b.CustomerCode );
if(CustomerName>!=null)
{
r.CustomerName = Customer.CustomerName; //loop add data CustomerName
}
}
}
I have no idea to do it. Help me please
I'm not sure if I understand your code but what about this:
var BillData = (from t1 in db2.Bill
select new {
BillCode = t1.Billcode,
CustomerCode = t1.Customer,
CustomerName = db1.Customer.FirstOrDefault(c => c.CustormerCode == t1.Customer)?.CustomerName
});
Then you have objects in BillData that holds the CustomerName and you can order by that:
BillData.OrderBy(bd => bd.CustomerName);
If you just want to get CustomerName from your customer Db and sort it, this is what i would have used. I used orderByDescending but you can use OrderBy aswell.
public List<Customer> getLogsByCustomerName(string customername)
{
using (var dbentites = new CustomerEntities())
{
var result = (from res in dbentites.Customer.OrderByDescending(_ => _.CustomerName)
where res.CustomerName == customername
select res).ToList();
return result.ToList();
}
}

Entity Framework 6 - Outer Joins and Method Syntax Queries

I'm trying to re-write the following SQL LEFT OUTER JOIN query using Entity Framework 6:
select tblA.*, tblB.*
from dbo.TableA tblA left outer join dbo.TableB tblB on
tblA.Student_id=tblB.StudentId and tblA.other_id=tblB.OtherId
where tblB.Id is null
Here's my current C# code:
using (var db = EFClass.CreateNewInstance())
{
var results = db.TableA.GroupJoin(
db.TableB,
tblA => new { StudentId = tblA.Student_id, OtherId = tblA.other_id },
tblB => new { tblB.StudentId, tblB.OtherId },
(tblA, tblB) => new { TableAData = tblA, TableBData = tblB }
)
.Where(x => x.TableBData.Id == null)
.AsNoTracking()
.ToList();
return results;
}
And here's the following compiler error I'm getting:
The type arguments cannot be inferred from the usage. Try specifying
the type arguments explicitly.
In a nutshell: I need to OUTER JOIN the two DbSet objects made available via Entity Framework, using more than one column in the join.
I'm also fairly certain this won't do a LEFT OUTER JOIN properly, even if I wasn't getting a compiler error; I suspect I need to involve the DefaultIfEmpty() method somehow, somewhere. Bonus points if you can help me out with that, too.
UPDATE #1: It works if I use a strong type in the join... is it simply unable to handle anonymous types, or am I doing something wrong?
public class StudentOther
{
public int StudentId { get; set; }
public int OtherId { get; set; }
}
using (var db = EFClass.CreateNewInstance())
{
var results = db.TableA.GroupJoin(
db.TableB,
tblA => new StudentOther { StudentId = tblA.Student_id, OtherId = tblA.other_id },
tblB => new StudentOther { StudentId = tblB.StudentId, OtherId = tblB.OtherId },
(tblA, tblB) => new { TableAData = tblA, TableBData = tblB }
)
.Where(x => x.TableBData.Id == null)
.AsNoTracking()
.ToList();
return results;
}
can you please try this solution? I'm not sure about the result :(
(from tblA in dbo.TableA
join tblB in dbo.TableB on new { tblA.Student_id, tblA.other_id } equals new { blB.StudentId, tblB.OtherId }
into tblBJoined
from tblBResult in tblBJoined.DefaultIfEmpty()
where tblBResult.Id == null
select new {
TableAData = tblA,
TableBData = tblB
}).ToList();

Selecting different rows in LINQ

I have two functions and a table with 2 rows. I want one function to select the first row and the other function to select the second row. I am a bit lost because I am very new to LINQ.
Here is my current code:
public static bool First() {
using (Entities db = new Entities()) {
DateTime FirstValue = (
from a in db.Table
select a.Timestamp
).Single();
public static bool Second() {
using (Entities db = new Entities()) {
DateTime SecondValue = (
from a in db.Table
select a.Timestamp
).Single();
I working with someone else's code and Im new to LINQ so I'm not sure what Single() does as well. I feel as though I do not need it in my code but I am not sure.
How about:
public static bool First() {
using (Entities db = new Entities()) {
DateTime FirstValue = (
from a in db.Table
select a.Timestamp
).FirstOrDefault();
public static bool Second() {
using (Entities db = new Entities()) {
DateTime SecondValue = (
from a in db.Table
select a.Timestamp
).Skip(1).FirstOrDefault();
#dkackman provided correct answer (use First/FirstOrDefault and Skip methods), but I want to mention that you can avoid mixing query syntax and method syntax, and methods could be simplified to:
public static DateTime First()
{
return GetByIndex(0);
}
public static DateTime Second()
{
return GetByIndex(1);
}
public static DateTime GetByIndex(int index)
{
using (Entities db = new Entities())
return db.Table.Select(a => a.TimeStamp).Skip(index).First();
}
Try like this,
private void First()
{
using (WinEntitie obj = new WinEntitie())
{
var FirstValue = (from a in obj.Employees select a.EmpName).Take(1);
}
}
private void Sec()
{
using (WinEntitie obj = new WinEntitie())
{
var FirstValue = (from a in obj.Employees orderby a.EmpID ascending select a.EmpName ).Skip(1).First();
}
}
Use common method for like this one what ever value you want to skip just pass it to the index. and also use the FirstOrDefault because the corresponding value returns null means it will take care or otherwise getting execption.
public static DateTime GetByIndex(int index)
{
using (Entities db = new Entities()) {
return db.Table.Select(a => a.TimeStamp).Skip(index).FirstOrDefault();
}
return null;
}
I was overwhelmed with LINQ that i should simply use a 'where' statement to locate something in my query...maybe I need a break

Refactoring C# code - doing more within Linq

The code below is what I currently have and works fine. I feel that I could do more of the work I am doing in Linq instead of C# code.
Is there is anyone out there who can accomplish the same result with more Linq code and less C# code.
public List<Model.Question> GetSurveyQuestions(string type, int typeID)
{
using (eMTADataContext db = DataContextFactory.CreateContext())
{
List<Model.Question> questions = new List<Model.Question>();
List<Linq.Survey_Question> survey_questions;
List<Linq.Survey> surveys = db.Surveys
.Where(s => s.Type.Equals(type) && s.Type_ID.Equals(typeID))
.ToList();
if (surveys.Count > 0)
{
survey_questions = db.Survey_Questions
.Where(sq => sq.Survey_ID == surveys[0].ID).ToList();
foreach (Linq.Survey_Question sq in survey_questions)
{
Model.Question q = Mapper.ToBusinessObject(sq.Question);
q.Status = sq.Status;
questions.Add(q);
}
}
else
{
questions = null;
}
return questions;
}
}
Here is my Mapper function from my Entity to Biz Object
internal static Model.Question ToBusinessObject(Linq.Question q)
{
return new Model.Question
{
ID = q.ID,
Name = q.Name,
Text = q.Text,
Choices = ToBusinessObject(q.Question_Choices.ToList())
};
}
I want my mapper funciton to map the Question Status like so.
internal static Model.Question ToBusinessObject(Linq.Question q)
{
return new Model.Question
{
ID = q.ID,
Name = q.Name,
Text = q.Text,
Choices = ToBusinessObject(q.Question_Choices.ToList()),
Status = q.Survey_Questions[?].Status
};
}
? the issue is this function does not know which survey to pull the status from.
Instead of creating the biz object then setting the Status property in a foreach loop like so
foreach (Linq.Survey_Question sq in survey_questions)
{
Model.Question q = Mapper.ToBusinessObject(sq.Question);
q.Status = sq.Status;
questions.Add(q);
}
I would like to somehow filter the EntitySet<Survey_Question> in the q object above in the calling method, such that there would only be one item in the q.Survey_Questions[?] collection.
below is my database schema and business object schema
What I needed to do was setup a join.
public List<Model.Question> GetSurveyQuestions(string type, int typeID)
{
using (eMTADataContext db = DataContextFactory.CreateContext())
{
return db.Survey_Questions
.Where(s => s.Survey.Type.Equals(type) && s.Survey.Type_ID.Equals(typeID))
.Join(db.Questions,
sq => sq.Question_ID,
q => q.ID,
(sq, q) => Mapper.ToBusinessObject(q, sq.Status)).ToList();
}
}
And then overload my Mapper Function
internal static Model.Question ToBusinessObject(Linq.Question q, string status)
{
return new Model.Question
{
ID = q.ID,
Name = q.Name,
Text = q.Text,
Status = status,
Choices = ToBusinessObject(q.Question_Choices.ToList()),
};
}
from question in db.Survey_Questions
let surveys = (from s in db.Surveys
where string.Equals(s.Type, type, StringComparison.InvariantCultureIgnoreCase) &&
s.Type_ID == typeID)
where surveys.Any() &&
surveys.Contains(s => s.ID == question.ID)
select new Mapper.Question
{
ID = question.Id,
Name = question.Name,
Text = question.Text,
Choices = ToBusinessObject(question.Question_Choices.ToList()),
Status = question.Status
}
Does that get you on the right track?
Why are you duplicating all your classes? You could just extend the LINQ to SQL classes with your business logic - they are partial classes. This is somewhat against the purpose of an OR mapper - persisting business entities.

Categories

Resources