I'm having the next issue, I have the next code
var creditos = from c in db.creditos
join s in db.solicitudDelCliente on c.SolicitudDelClienteID equals s.ID
join cl in db.cliente on s.ClienteID equals cl.ID
where c.Eliminado != true && cl.Eliminado != true && c.NegocioID == negocio_id
select new
{
c.ID,
cl.NumeroCliente,
c.Consecutivo,
NegocioID = negocio_id,
cl.NombreCompleto,
c.FechaAlta,
c.CapitalPrestado,
c.Vencido,
c.Quebranto,
c.Juridico,
c.Liquidado,
c.Reestructura,
c.Eliminado,
c.Estatus,
CapitalPagado = db.movimientos.Where(mm=>mm.CreditoID == c.ID && mm.Eliminado != true && mm.DepositoMovimientoID != null && mm.CategoriaMovimientosID == 2).Select(mm=>mm.Monto).DefaultIfEmpty(0).Sum(),
InteresesPagados = db.movimientos.Where(mm => mm.CreditoID == c.ID && mm.Eliminado != true && mm.DepositoMovimientoID != null && mm.CategoriaMovimientosID == 4).Select(mm => mm.Monto).DefaultIfEmpty(0).Sum(),
SaldoInsoluto = db.movimientos.Where(mm => mm.CreditoID == c.ID && mm.CategoriaMovimientosID == 1).Select(mm => mm.Monto).DefaultIfEmpty(0).Sum() -
db.movimientos.Where(mm => mm.CreditoID == c.ID && mm.Eliminado != true && mm.DepositoMovimientoID != null && mm.CategoriaMovimientosID == 2).Select(mm => mm.Monto).DefaultIfEmpty(0).Sum(),
SaldoDeudorTotal = (db.movimientos.Where(mm => mm.CreditoID == c.ID
&& mm.Eliminado != true
&& mm.DepositoMovimientoID == null
&& mm.CategoriaMovimientosID != 2)
.Select(mm => mm.Monto).DefaultIfEmpty(0).Sum()
- db.movimientos.Where(mm => mm.CreditoID == c.ID
&& mm.Eliminado != true
&& mm.DepositoMovimientoID != null
&& mm.CategoriaMovimientosID != 1)
.Select(mm => mm.Monto).DefaultIfEmpty(0).Sum()),
Migrado = c.Migracion
};
In some of the results of the query, the value of "SaldoDeudorTotal" is negative, I want to control the value, that if the value is -0 then return 0 zero.
var creditos = from c in db.creditos
join s in db.solicitudDelCliente on c.SolicitudDelClienteID equals s.ID
join cl in db.cliente on s.ClienteID equals cl.ID
where c.Eliminado != true && cl.Eliminado != true && c.NegocioID == negocio_id
let total = (db.movimientos.Where(mm => mm.CreditoID == c.ID
&& mm.Eliminado != true
&& mm.DepositoMovimientoID == null
&& mm.CategoriaMovimientosID != 2)
.Select(mm => mm.Monto).DefaultIfEmpty(0).Sum()
- db.movimientos.Where(mm => mm.CreditoID == c.ID
&& mm.Eliminado != true
&& mm.DepositoMovimientoID != null
&& mm.CategoriaMovimientosID != 1)
.Select(mm => mm.Monto).DefaultIfEmpty(0).Sum())
select new
{
c.ID,
cl.NumeroCliente,
c.Consecutivo,
NegocioID = negocio_id,
cl.NombreCompleto,
c.FechaAlta,
c.CapitalPrestado,
c.Vencido,
c.Quebranto,
c.Juridico,
c.Liquidado,
c.Reestructura,
c.Eliminado,
c.Estatus,
CapitalPagado = db.movimientos.Where(mm=>mm.CreditoID == c.ID && mm.Eliminado != true && mm.DepositoMovimientoID != null && mm.CategoriaMovimientosID == 2).Select(mm=>mm.Monto).DefaultIfEmpty(0).Sum(),
InteresesPagados = db.movimientos.Where(mm => mm.CreditoID == c.ID && mm.Eliminado != true && mm.DepositoMovimientoID != null && mm.CategoriaMovimientosID == 4).Select(mm => mm.Monto).DefaultIfEmpty(0).Sum(),
SaldoInsoluto = db.movimientos.Where(mm => mm.CreditoID == c.ID && mm.CategoriaMovimientosID == 1).Select(mm => mm.Monto).DefaultIfEmpty(0).Sum() -
db.movimientos.Where(mm => mm.CreditoID == c.ID && mm.Eliminado != true && mm.DepositoMovimientoID != null && mm.CategoriaMovimientosID == 2).Select(mm => mm.Monto).DefaultIfEmpty(0).Sum(),
SaldoDeudorTotal = total < 0 ? 0 : total,
Migrado = c.Migracion
};
you could use an extension
public static class MyExtension
{
public static int ToPositiveInt(this int value)
{
if (value < 0)
return 0;
else
return value
}
}
and call it at the end of your condition of SaldoDeudorTotal
SaldoDoeudorTotal = (db.movimientos.Where(mm => mm.CreditoID == c.ID
&& mm.Eliminado != true
&& mm.DepositoMovimientoID == null
&& mm.CategoriaMovimientosID != 2).ToPositiveInt()
Related
I have looked at similar questions but none have really been able to answer my question.
All I want to do is make a select using lambda but the trick is, there is a variable amount of OR/AND conditions for the selection. My function receives a list of AND conditions and it should select based on that.
Here is what I have right now and it supports up to 10 AND conditions passed as a string to compare, but this code is terrible.. in reality it should be able to accept an undefined/variable amount of conditions.
Not sure how to go about this..
ProductTags is a list of tags.. if the product has all of the tags then it is returned.
public static List<product> FilterProductsByTagsAll(List<string> tags)
{
List<product> products = new List<product>();
switch (tags.Count)
{
case 1:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()).ToList();
break;
case 2:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()).ToList();
break;
case 3:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()).ToList();
break;
case 4:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()).ToList();
break;
case 5:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()).ToList();
break;
case 6:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()).ToList();
break;
case 7:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()).ToList();
break;
case 8:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[7]).Any()).ToList();
break;
case 9:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[7]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[8]).Any()).ToList();
break;
case 10:
products = Database.Products.Values.Where(i => i.ProductTags != null
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[0]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[1]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[2]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[3]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[4]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[5]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[6]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[7]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[8]).Any()
&& i.ProductTags.Where(i => i != null && i.Tag_name == tags[9]).Any()).ToList();
break;
default:
break;
}
return products;
}
Thank you for trying to help out.
Try this query:
var allTagsProds = Database.Products.Values.Where(p => p.ProductTags != null && p.ProductTags.Select(pt => pt.Tag_name).Intersect(tags).Count() == tags.Count());
For each product, it selects the product tag names then intersects them with the tags list. This produces a list of product tag names that match the tags list.
Then it compares the count of this list with the count of the tags list and if they are the same, the product has all the tags. These are then returned.
Example using hard coded models:
public class Tag {
public string Tag_name {get; set;}
}
public class Product {
public ICollection<Tag> ProductTags {get; set;}
public string Name {get; set;}
}
public class Program
{
public static void Main()
{
List<string> tags = new List<string> {"a","b","c","d","e","f"};
var prodTags = new List<Tag>() {
new Tag() {Tag_name = "a"},
new Tag() {Tag_name = "b"},
new Tag() {Tag_name = "c"},
new Tag() {Tag_name = "d"}
};
var prodTags2 = new List<Tag>() {
new Tag() {Tag_name = "a"},
new Tag() {Tag_name = "b"},
new Tag() {Tag_name = "c"},
new Tag() {Tag_name = "d"},
new Tag() {Tag_name = "e"},
new Tag() {Tag_name = "f"}
};
var products = new List<Product>() {
new Product() { Name="Prod1", ProductTags = prodTags },
new Product() { Name="Prod2",ProductTags = prodTags2 }
};
var allTagsProds = products.Where(p => p.ProductTags != null && p.ProductTags.Select(pt => pt.Tag_name).Intersect(tags).Count() == tags.Count());
foreach(var prod in allTagsProds)
{
//Writes "Prod2"
Console.WriteLine(prod.Name);
}
}
}
I have this EF query
var r = (from cd in _context.CentoData
.Where(c =>
(string.IsNullOrEmpty(geneName) ? true : c.Gene == geneName) &&
(string.IsNullOrEmpty(codingEffect) ? true : c.CodingEffect == codingEffect) &&
(string.IsNullOrEmpty(zygosity) ? true : c.Zygosity == zygosity) &&
(string.IsNullOrEmpty(sex) ? true : c.Sex == sex) &&
(string.IsNullOrEmpty(clinicalStatement) ? true : c.ClinicalStatement == clinicalStatement) &&
(onsetAge == null ? true : c.AgeAtDiagnosisYearsMonths < onsetAge))
from gs in _context.GnomadSnv
.Where(g => g.Chromosome == cd.Chromosome &&
g.Position == cd.Position &&
g.Ref == cd.RefNt &&
g.Alt == cd.AltNt)
.DefaultIfEmpty()
select new resultType
{
name = cd.name,
AF = g.AF
}
And it works well. But when I when I include a Contains subquery as below (line 9), it pops error saying
"The multi-part identifier "c.Chromosome" could not be bound".
patients is a string list with tens to hundreds elements.
var r = (from cd in _context.CentoData
.Where(c =>
(string.IsNullOrEmpty(geneName) ? true : c.Gene == geneName) &&
(string.IsNullOrEmpty(codingEffect) ? true : c.CodingEffect == codingEffect) &&
(string.IsNullOrEmpty(zygosity) ? true : c.Zygosity == zygosity) &&
(string.IsNullOrEmpty(sex) ? true : c.Sex == sex) &&
(string.IsNullOrEmpty(clinicalStatement) ? true : c.ClinicalStatement == clinicalStatement) &&
(onsetAge == null ? true : c.AgeAtDiagnosisYearsMonths < onsetAge) &&
(patients != null ? patients.Contains(c.RandomPatientId): true))
from gs in _context.GnomadSnv
.Where(g => g.Chromosome == cd.Chromosome &&
g.Position == cd.Position &&
g.Ref == cd.RefNt &&
g.Alt == cd.AltNt)
.DefaultIfEmpty()
select new resultType
{
name = cd.name,
AF = g.AF
}
Did I miss something here?
How to match list values in linq condition?
I have one list of IDs, so these ids have to match in condition and get data from one table sol how?
public ActionResult StudentSelect(
long? CompanyId,
long? CompanyLocationId,
long? ClassId,
long? SectionId,
long? AcademicId,
long? ExamId) //) //long? SectionId)
Below RegId is list of student's registration Ids
{
var RegId = (
from a in db.Student_Marks_Percentage
where a.Delete_Flag == false &&
a.Exam_Id == ExamId &&
a.Academic_Year_Id == AcademicId &&
a.Class_Id == ClassId
select a.Registration_Id)
.ToList();
List<StudentList> Student = new List<StudentList>();
if (AcademicId != null &&
CompanyId != null &&
CompanyLocationId != null &&
ClassId == null &&
SectionId == null) //&& )//&& ClassId != null) //)
{
Student = (
from a in db.Student_Re_Admission
join b in db.Student_Registration on a.Registration_Id equals b.Registration_Id
join c in db.Student_Roll_No_Assign on a.Registration_Id equals c.Registration_Id
where c.Academic_Year_Id == AcademicId &&
c.Company_ID == CompanyId &&
c.COMPANY_LOCATION_ID == CompanyLocationId &&
a.Academic_Year_Id == AcademicId &&
c.Class_Id == ClassId &&
a.Class_Id == ClassId &&
a.Section_Id == SectionId &&
c.Section_Id == SectionId &&
Here I have to compare those all list of ids to a.Registration_Id
a.Registration_Id != RegIds &&
a.Promoted == false &&
a.Delete_Flag == false
//a.Academic_Year_Id == AcademicId &&
//a.Company_ID == CompanyId &&
//a.COMPANY_LOCATION_ID == CompanyLocationId
select new StudentList()
{
Registration_Id = a.Registration_Id,
Admission_No = a.Admission_No,
Student_First_Name = a.Student_First_Name,
Student_Middle_Name = a.Student_Middle_Name,
Student_Last_Name = a.Student_Last_Name,
Set_Roll_No = c.Set_Roll_No,
Roll_Id = c.Roll_Id
})
.OrderBy(a => a.Registration_Id)
.ToList();
ViewBag.StudentList = Student.ToList();
return PartialView();
}
}
I tried like below but getting same data of student list..
var merged = new List<StudentList>(Student);
merged.Except(Student.Where(p2 => RegId.Exists(p1 => p2.Registration_Id != p1.Registration_Id)));
I think you just need to replace a.Registration_Id != RegIds with:
!RegIDs.Contains(a.Registration_Id)
First var list by which have to compare
var RegId = (from a in db.Student_Marks_Percentage
where a.Delete_Flag == false
&& a.Exam_Id == ExamId
&& a.Academic_Year_Id == AcademicId
&& a.Class_Id == ClassId
select a).ToList();
second list of which data have to get
List<StudentList> Student = new List<StudentList>();
if (AcademicId != null && CompanyId != null && CompanyLocationId != null && ClassId == null && SectionId == null) //&& )//&& ClassId != null) //)
{
Student = (from a in db.Student_Re_Admission
join b in db.Student_Registration on a.Registration_Id equals b.Registration_Id
join c in db.Student_Roll_No_Assign on a.Registration_Id equals c.Registration_Id
where c.Academic_Year_Id == AcademicId && c.Company_ID == CompanyId && c.COMPANY_LOCATION_ID == CompanyLocationId
&& a.Academic_Year_Id == AcademicId && c.Class_Id == ClassId && a.Class_Id == ClassId
&& a.Section_Id == SectionId && c.Section_Id == SectionId
//&& a.Registration_Id != RegId.Contains(a.Registration_Id)
&& a.Promoted == false && a.Delete_Flag == false
//a.Academic_Year_Id == AcademicId && a.Company_ID == CompanyId && a.COMPANY_LOCATION_ID == CompanyLocationId
select new StudentList()
{
Registration_Id = a.Registration_Id,
Admission_No = a.Admission_No,
Student_First_Name = a.Student_First_Name,
Student_Middle_Name = a.Student_Middle_Name,
Student_Last_Name = a.Student_Last_Name,
Set_Roll_No = c.Set_Roll_No,
Roll_Id = c.Roll_Id
}).OrderBy(a => a.Registration_Id).ToList();
}
merging two lists by searching following process.
var merged = Student.Where(a1 => !RegId.Any(a2 => a1.Registration_Id == a2.Registration_Id));
I have following method that registers a contact in database, but before register I check the contact exists or not:
bool RegisterContact(Contact contactInfo) {
bool entityExists =
_dbContext.Contacts.FirstOrDefault(
p => (p.FilesID.Equals(contactInfo.FilesID))
&& (p.EmailAddress ==
(string.IsNullOrEmpty(
contactInfo.EmailAddress)
? p.EmailAddress
: contactInfo.EmailAddress))
&&
(p.DisplayName ==
(string.IsNullOrEmpty(
contactInfo.DisplayName)
? p.DisplayName
: contactInfo.DisplayName)));
}
this query includes the fields that contain value (not null) in search condition (FilesID, EmailAddress, DisplayName)
this technique works fine in MSSQL, today i changed the database manager to PostgreSQL and use Npgsql.
All things work except above linq query, which raises an exception with message of : "could not determine data type of parameter $2"
I was forced to solve it in this way:
bool RegisterContact(Contact contactInfo)
{
Contact entityExists = null;
if (string.IsNullOrEmpty(contactInfo.EmailAddress) &&
(string.IsNullOrEmpty(contactInfo.DisplayName)))
entityExists =
_dbContext.Contacts.FirstOrDefault(
p => p.FilesID.Equals(contactInfo.FilesID));
if (!string.IsNullOrEmpty(contactInfo.EmailAddress) && string.IsNullOrEmpty(contactInfo.DisplayName))
entityExists =
_dbContext.Contacts.FirstOrDefault(
p =>
p.FilesID.Equals(contactInfo.FilesID) &&
p.EmailAddress == contactInfo.EmailAddress);
if (string.IsNullOrEmpty(contactInfo.EmailAddress) && !string.IsNullOrEmpty(contactInfo.DisplayName))
entityExists =
_dbContext.Contacts.FirstOrDefault(
p =>
p.FilesID.Equals(contactInfo.FilesID) &&
p.DisplayName == contactInfo.DisplayName);
if (!string.IsNullOrEmpty(contactInfo.EmailAddress) &&
!string.IsNullOrEmpty(contactInfo.DisplayName))
entityExists =
_dbContext.Contacts.FirstOrDefault(
p =>
p.FilesID.Equals(contactInfo.FilesID) &&
p.EmailAddress == contactInfo.EmailAddress &&
p.DisplayName == contactInfo.DisplayName);
}
Is this Npgsql bug or by design? any known solutions/workarounds for the problem?
I currently have the same cases. I think the problem is the lack of recognition, by NpgSQL, of string.IsNullOrEmpty.
I replaced the test with a check on empty string, always recognizing as not NULL the input parameter.
-- bad
var data = from art in _ctx.Set<Soleo.Model.DLAR>()
from iva in _ctx.Set<Soleo.Model.DLAI>().Where(k => k.DITTA == art.DITTA && k.COD == art.CIVA).DefaultIfEmpty()
from fam in _ctx.Set<Soleo.Model.DLFA>().Where(k => k.DITTA == art.DITTA && k.COD == art.FAM).DefaultIfEmpty()
from mar in _ctx.Set<Soleo.Model.DLMA>().Where(k => k.DITTA == art.DITTA && k.COD == art.MAR).DefaultIfEmpty()
from udm in _ctx.Set<Soleo.Model.DLUM>().Where(k => k.DITTA == art.DITTA && k.COD == art.UM).DefaultIfEmpty()
where art.DITTA == DLAUTH.Config.Current.DITTA && art.COD.Contains(sel_cod) && art.DES.Contains(sel_des)
&& (string.IsNullOrEmpty(sel_fam) || string.Compare(art.FAM, sel_fam, true) == 0)
&& (string.IsNullOrEmpty(sel_mar) || string.Compare(art.MAR, sel_mar, true) == 0)
&& (art.DIS >= sel_dis_da && art.DIS <= sel_dis_a)
select new
{
COD = art.COD,
DES = art.DES,
DES_UDM = udm.DES,
DES_MAR = mar.DES,
DES_FAM = fam.DES,
DES_CIVA = iva.DES,
MAG1 = art.MAG1,
MAG2 = art.MAG2,
DES_DIS = art.DIS == 1 ? "Si" : "No"
};
-- good:
var data = from art in _ctx.Set<Soleo.Model.DLAR>()
from iva in _ctx.Set<Soleo.Model.DLAI>().Where(k => k.DITTA == art.DITTA && k.COD == art.CIVA).DefaultIfEmpty()
from fam in _ctx.Set<Soleo.Model.DLFA>().Where(k => k.DITTA == art.DITTA && k.COD == art.FAM).DefaultIfEmpty()
from mar in _ctx.Set<Soleo.Model.DLMA>().Where(k => k.DITTA == art.DITTA && k.COD == art.MAR).DefaultIfEmpty()
from udm in _ctx.Set<Soleo.Model.DLUM>().Where(k => k.DITTA == art.DITTA && k.COD == art.UM).DefaultIfEmpty()
where art.DITTA == DLAUTH.Config.Current.DITTA && art.COD.Contains(sel_cod) && art.DES.Contains(sel_des)
&& (string.Compare(sel_fam, "", true) == 0 || string.Compare(art.FAM, sel_fam, true) == 0)
&& (string.Compare(sel_mar, "", true) == 0 || string.Compare(art.MAR, sel_mar, true) == 0)
&& (art.DIS >= sel_dis_da && art.DIS <= sel_dis_a)
select new
{
COD = art.COD,
DES = art.DES,
DES_UDM = udm.DES,
DES_MAR = mar.DES,
DES_FAM = fam.DES,
DES_CIVA = iva.DES,
MAG1 = art.MAG1,
MAG2 = art.MAG2,
DES_DIS = art.DIS == 1 ? "Si" : "No"
};
But I do not think this is the solution. I will report the case to NpgSQL.
I am using LINQ query in my code which need to be write multiple times with small changes in where condition. My query is
var sdata = from r in dt.AsEnumerable()
where r.Field<DateTime>("DAT_START").TimeOfDay.Hours < 20 &&
r.Field<DateTime>("DAT_START").TimeOfDay.Hours >= 4
group r by r["TXT_TARGET_CELL_ID"] into g
select new
{
CellID = g.Key,
TotalCommCount = g.Count(),
TotalDuration = g.Sum(r => r.Field<int>("LNG_DURATION")),
InSMSCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 1 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 5),
OutSMSCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 2 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 5),
InVoiceCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 1 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1),
OutVoiceCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 2 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1),
InVoiceDuration = g.Where(r => r.Field<Int16>("INT_DIRECTION") == 1 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1)
.Sum(r => r.Field<int>("lNG_DURATION")),
OutVoiceDuration = g.Where(r => r.Field<Int16>("INT_DIRECTION") == 2 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1)
.Sum(r => r.Field<int>("LNG_DURATION")),
Latitude = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_LATITUDE") : "",
Longitude = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_LONGITUDE") : "",
BTS_Address = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_TARGET_BTS_LOCATION_ADDRESS") : "",
Azimuth = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_AZIMUTH_DEG") : ""
} into summary
orderby summary.TotalCommCount descending
select summary;
Here i need to change where condition only every time, remaining part remain same i.e Select new part. Can i write this query once in code and make a call to it with change in where condition ?
You can break your predicate out into a separate method;
private static bool Where1(DT r)
{
return r.Field<DateTime>("DAT_START").TimeOfDay.Hours < 20 &&
r.Field<DateTime>("DAT_START").TimeOfDay.Hours >= 4
}
This will be assignable to a Func that you can use right in your expression;
Func<DT, bool> myWhere
if(whereCase1) // Decide which Where predicate to use
myWhere = Where1;
else
myWhere = Where2;
var sdata = from r in dt.AsEnumerable()
where myWhere(r) // Use the chosen Where predicate.
group r by r["TXT_TARGET_CELL_ID"]
into g
select new...
To build the Where condition in a slightly more dynamic way, you can make a function that returns the where condition instead of a bool;
private static Func<DT, bool> WhereHoursAreBetween(int min, int max)
{
return r => r.Field<DateTime>("DAT_START").TimeOfDay.Hours < max &&
r.Field<DateTime>("DAT_START").TimeOfDay.Hours >= min;
}
...which can then be used in the above example as;
myWhere = WhereHoursAreBetween(4, 20);
...which makes myWhere a condition that hours are between 4 and 20.
Just make a new function like this:
public dynamic MyLinq(IEnumerable r, Predicate<Object> whereClause)
{
return from r
where whereClause(r)
group r by r["TXT_TARGET_CELL_ID"] into g
select new
{
CellID = g.Key,
TotalCommCount = g.Count(),
TotalDuration = g.Sum(r => r.Field<int>("LNG_DURATION")),
InSMSCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 1 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 5),
OutSMSCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 2 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 5),
InVoiceCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 1 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1),
OutVoiceCount = g.Count(r => r.Field<Int16>("INT_DIRECTION") == 2 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1),
InVoiceDuration = g.Where(r => r.Field<Int16>("INT_DIRECTION") == 1 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1)
.Sum(r => r.Field<int>("lNG_DURATION")),
OutVoiceDuration = g.Where(r => r.Field<Int16>("INT_DIRECTION") == 2 &&
r.Field<Int16>("INT_CALL_DATA_TYPE") == 1)
.Sum(r => r.Field<int>("LNG_DURATION")),
Latitude = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_LATITUDE") : "",
Longitude = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_LONGITUDE") : "",
BTS_Address = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_TARGET_BTS_LOCATION_ADDRESS") : "",
Azimuth = g.Any(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "") ? g.First(s => s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS") != null && s.Field<string>
("TXT_TARGET_BTS_LOCATION_ADDRESS").Trim() != "").Field<string>("TXT_AZIMUTH_DEG") : ""
} into summary
orderby summary.TotalCommCount descending
select summary;
}
Furthermore you should really be using constants for things like "TXT_TARGET_BTS_LOCATION_ADDRESS" because it saves you from a simple mistake such as writing: "TXT_TARGET_BTS_LOCAITON_ADDRESS" and having it be compile time safe.
Edit: You would call this function with something like this:
var sdata = MyLinq(dt.AsEnumerable(), r => r.Field<DateTime>("DAT_START").TimeOfDay.Hours < 20 && r.Field<DateTime>("DAT_START").TimeOfDay.Hours >= 4)
you will probably need to change Object in Predicate<Object> to your actual type so that you can access the .Field values.
Create a function which receives a Predicate. Something like:
dynamic MyLinq(Predicate<Object> Check)
{
return from r in dt.AsEnumerable()
where Check(r)
select r;
}
Yes, you can refactor the expression by extracting the where part to a separate expression and then using it inside the bigger expression.