How to convert this sql to efcore linq - c#

Original data sheet:
SQL that can get the result you want:
select group_number,count(group_number) as group_count,receive_date
from hS_HZXX
where type = '1'
group by group_number,receive_date;
use ef core linq like this:
var hAATGroups = from p in dbContext.Set<HS_HZXX>()
where p.type == "1"
group p by new { Group_number = p.group_number, Sampling_date = p.sampling_date } into dto
select new DTO_HAATGroup
{
Group_number = dto.Key.Group_number,
HAAT_count = dto.Key.Group_number.Count(),
Sampling_date = dto.Key.Sampling_date.ToString("yyyy-MM-dd")
};
The DTO_HAATGroup:
public class DTO_HAATGroup
{
public string Group_number { get; set; }
public int HAAT_count { set; get; }
public string Sampling_date { get; set; }
}
The result of executing linq:
But I got the wrong result. . . Can you help me? How can I convert this SQL into a correct Linq statement.

I have solved this problem, the correct Linq writing is as follows:
var hAATGroups = from p in dbContext.Set<HS_HZXX>()
where p.type == "1"
group p by new { Group_number = p.group_number, Receive_date = p.receive_date } into dto
select new DTO_HAATGroup
{
Group_number = dto.Key.Group_number,
HAAT_count = dto.Count(),
Receive_date = dto.Key.Receive_date.ToString("yyyy-MM-dd")
};

Related

How to retrieve data from dynamic table in mvc

I'm writing new api call for my android app, I want to retrieve data from dynamic table, I mean when user select "A" button from Andriod I want to retrieve data from "A" table and if "B" is click , retrieve data from "B" table. Someone help me to find the possible solution.
I want to replace with variable for "JBCTNRITEMs" from entities.JBCTNRITEMs (table-name)
var query = (from jbct in entities.JBCTNRITEMs
where jbid.Contains(jbct.jbid.ToString()) && boxid.Contains(jbct.TrackingNo.ToString())
select jbct).ToArray();
int id = 0;
if (query.Length > 0)
{
id = (query[0].id);
}
return id;
Here are the two different possibilities as an example
if (module.ToLower() == "module-a")
{
var imageinfo = (from jb in entities.TableA.AsEnumerable()
where scanID.Contains(jb.aid.ToString())
select jb).ToArray();
InsertGENIMAGE(userID, scanID, FilePath, imageinfo, "AIMAGE");
}
else if (module.ToLower() == "module-b")
{
var imageinfo = (from jb in entities.TableB.AsEnumerable()
where scanID.Contains(jb.bid.ToString())
select jb).ToArray();
InsertGENIMAGE(userID, scanID, FilePath, imageinfo, "BIMAGE");
}
Here, query stores what you are you trying to select. As long as you are trying to select same type or same anonymous type, it will work.
Here is a simple example:
class Test1
{
public int ID { get; set; }
public string Name { get; set; }
}
class Test2
{
public int ID { get; set; }
public string Name { get; set; }
}
var test1Lst = new List<Test1>
{
new Test1() { ID = 1, Name = "Jitendra" },
new Test1() { ID = 2, Name = "Jahnavi" }
};
var test2Lst = new List<Test2>
{
new Test2() { ID = 1, Name = "Aaditri" },
new Test2() { ID = 2, Name = "Pankaj" }
};
var test = false;
var query = test ? (from t in test1Lst select new { ID = t.ID, Name = t.Name }) : (from t in test2Lst select new { ID = t.ID, Name = t.Name });
// Put whatever condition you want to put here
query = query.Where(x => x.ID == 1);
foreach(var t1 in query)
{
Console.WriteLine(t1.ID + " " + t1.Name);
}
I guess in this case I would suggest to use a generic method :
private T GetMeTheFirstEntry<T>(Expression<Func<T, bool>> filter) where T : class
{
return entities.GetTable<T>().FirstOrDefault(filter);
}
The GetTable will allow you to interchange the tableA and tableB. You would call it the following way:
TableA tableA_entity = GetMeTheFirstEntry<TableA>(jb => scanID.Contains(jb.aid.ToString()));
TableB tableB_entity = GetMeTheFirstEntry<TableB>(jb => scanID.Contains(jb.bid.ToString()));
If the filtering was successfull, then the retrieved object will not be null and you can use it:
int a_id = tableA_entity.aid;

Unable to convert AnonymousType#1 ti IEnumerable

I have declared a model in my .cs page
public class InstrumentDetails
{
public long PullNo { get; set; }
public string Description { get; set; }
public int New { get; set; }
public int LN { get; set; }
public int PR { get; set; }
public int Any { get; set; }
}
After that i am retrieving data like this way :
IEnumerable<InstrumentDetails> instrumentdetails = (from p in NemcDb.tblPulls
join
pi in NemcDb.tblPullInstruments
on
p.PullId equals pi.PullId
join
i in NemcDb.tblInstruments
on
pi.InstrumentCode equals i.InstrumentCode
select new
{
PullNo = p.PullNo.Value,
InstrumentType = i.Description,
New = pi.NewQuantity,
LN = pi.LNQuantity,
PR = pi.UsedQuantity,
Any = pi.AnyQuantity
}).Where(i => i.PullNo.ToString() == item);
But it gives me the error
Cannot convert 'System.Linq.IQueryable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<>'. An explicit conversion exists (are you missing a cast?)
Where am I wrong?...I couldn't get it through....Please help.
You don't tell that you want an object of type InstrumentDetails, you create an anonymous type. Change select new { ... into select new InstrumentDetails { ... and then also call ToList(), ToEnumerable() or ToArray() in the end so the query is actually run.
The answer would be :
IEnumerable<InstrumentDetails> instrumentdetails = (from p in NemcDb.tblPulls
join
pi in NemcDb.tblPullInstruments
on
p.PullId equals pi.PullId
join
i in NemcDb.tblInstruments
on
pi.InstrumentCode equals i.InstrumentCode
select new InstrumentDetails
{
PullNo = p.PullNo.Value,
InstrumentType = i.Description,
New = pi.NewQuantity,
LN = pi.LNQuantity,
PR = pi.UsedQuantity,
Any = pi.AnyQuantity
}).Where(i => i.PullNo.ToString() == item).ToList();
}
How Silly of me............

How to distinct by multiple columns with input parameter in Linq

i have tre tables T020_CLIENTI,T021_SITI,T520_REL_STRUMENTI_SITI that i would join and then distinct by T020.Ragione_sociale,T520.DA_DATA,T520.A_DATA but obtain as return parameters T020.Ragione_sociale,T020.id_cliente,T520.cod_stumento,T520.DA_DATA,T520.A_DATA
my tables are
public partial class T020_CLIENTI
{
public decimal ID_CLIENTE { get; set; }
public Nullable<decimal> ID_COMUNE { get; set; }
public Nullable<decimal> ID_CONSORZIO { get; set; }
public string COD_LINEA_ATTIVITA { get; set; }
}
public partial class T021_SITI
{
public decimal ID_SITO { get; set; }
public Nullable<decimal> ID_FORNITORE { get; set; }
public Nullable<decimal> ID_CLIENTE { get; set; }
}
public partial class T520_REL_STRUMENTI_SITI
{
public string COD_STUMENTO { get; set; }
public decimal ID_SITO { get; set; }
public System.DateTime DA_DATA { get; set; }
public System.DateTime A_DATA { get; set; }
}
my linq query is
using (var cont = DALProvider.CreateEntityContext())
{
var query =
from cliente in cont.T020_CLIENTI
from sito
in cont.T021_SITI
.Where(s => s.ID_CLIENTE == cliente.ID_CLIENTE)
.DefaultIfEmpty()
from relStrumenti
in cont.T520_REL_STRUMENTI_SITI
.Where(s => s.ID_SITO == sito.ID_SITO)
.DefaultIfEmpty()
select new
{
clienteRec = cliente,
sitoRec = sito,
relStrumentiRec = relStrumenti
};
if (!string.IsNullOrEmpty(aiFiltro.RAGIONE_SOCIALE))
query = query.Where(i => i.clienteRec.RAGIONE_SOCIALE.ToUpper().Contains(aiFiltro.RAGIONE_SOCIALE.ToUpper()));
var vRes = (from clienteDef in query
select new ClienteFiltrato
{
RAGIONE_SOCIALE = clienteDef.clienteRec.RAGIONE_SOCIALE,
ID_CLIENTE = clienteDef.clienteRec.ID_CLIENTE,
COD_STRUMENTO = clienteDef.relStrumentiRec.COD_STUMENTO,
DATA_DA = clienteDef.relStrumentiRec.DA_DATA,
DATA_A = clienteDef.relStrumentiRec.A_DATA
}) ;
return vRes.AsQueryable();
}
but in my linq query i don't know where i can insert distinct and input parameter (:pPOD) to obtain my linq that in oracle query is:
SELECT DISTINCT t020.ragione_sociale,
da_data,
a_data,
t020.id_Cliente,
:pPOD
FROM t020_clienti t020, t021_siti t021, T520_REL_STRUMENTI_SITI t520
WHERE t020.id_cliente = t021.id_cliente
AND t021.id_sito = t520.id_sito
AND (:pPOD is null or t520.cod_stumento = :pPOD)
ORDER BY da_data
where :pPOD is an input parameter that i could have set or not.
Try to add (s.COD_STUMENTO == pPod || pPod == null) to your Where clause, where you are filtering T520_REL_STRUMENTI_SITI entity. pPod should be a string variable.
Please have in mind that if you are using DefaultIfEmpty() in LINQ this will be translated to left join in SQL.
Modified query follows:
string pPod = null;
using (var cont = DALProvider.CreateEntityContext())
{
var query =
(from cliente in cont.T020_CLIENTI
from sito
in cont.T021_SITI
.Where(s => s.ID_CLIENTE == cliente.ID_CLIENTE)
.DefaultIfEmpty()
from relStrumenti
in cont.T520_REL_STRUMENTI_SITI
.Where(s => s.ID_SITO == sito.ID_SITO && (s.COD_STUMENTO == pPod || pPod == null))
.DefaultIfEmpty()
select new
{
clienteRec = cliente.Distinct(),
sitoRec = sito,
relStrumentiRec = relStrumenti
});
if (!string.IsNullOrEmpty(aiFiltro.RAGIONE_SOCIALE))
query = query.Where(i => i.clienteRec.RAGIONE_SOCIALE.ToUpper().Contains(aiFiltro.RAGIONE_SOCIALE.ToUpper()));
var vRes = (from clienteDef in query
select new ClienteFiltrato
{
RAGIONE_SOCIALE = clienteDef.clienteRec.RAGIONE_SOCIALE,
ID_CLIENTE = clienteDef.clienteRec.ID_CLIENTE,
COD_STRUMENTO = clienteDef.relStrumentiRec.COD_STUMENTO,
DATA_DA = clienteDef.relStrumentiRec.DA_DATA,
DATA_A = clienteDef.relStrumentiRec.A_DATA
}).Distinct() ;
return vRes.AsQueryable();
}
You can use:
string query =
((System.Data.Objects.ObjectQuery)query).ToTraceString();
This will show you the generated SQL from LINQ Queryable object.

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();

Dynamic Grouping Using LINQ

Please have a look at below example. The Group Clause has to be dynamic. Can you please guide me how this can be achieved. i.e. the row
{ r.Portfolio, r.DataType }
has to be constructed dynamically.
Not sure how I can tweak the solution as given at blog http://jonahacquah.blogspot.com/2012/02/groupby-multiple-columns-using-dynamic.html
public class DecisionSupportData
{
public string Portfolio { get; set; }
public string BucketName { get; set; }
public string DataType { get; set; }
public string ChildPortfolio { get; set; }
}
public void PopulateData()
{
List<DecisionSupportData> lstAllDecSupp = decisionSupportDataBindingSource.DataSource as List<DecisionSupportData>;
List<DecisionSupportData> lstRmgAmt
= (from r in lstAllDecSupp.AsEnumerable()
where r.DataType == "P"
group r by new { r.Portfolio, r.DataType } into gg
select new DecisionSupportData
{
DataType = gg.Key.DataType,
Portfolio = gg.Key.Portfolio,
}).ToList();
}
The DynamicLinq library would appear to solve your issue, as mentioned in Scott Gu's original blog. Just use the GroupBy extension method with a string value.
Or you could dig into their ExpressionParser class and see what it's doing.
The following should work with your example, but may not work/scale up very well if your real-life example is more complicated.
// bools to indicate which columns you want to group by
bool groupByPortfolio = true;
bool groupByDataType = true;
bool groupByBucketName = false;
bool groupByChildPortfolio = false;
List<DecisionSupportData> lstRmgAmt
= (from r in lstAllDecSupp.AsEnumerable()
where r.DataType == "P"
group r by new
{
Portfolio = groupByPortfolio ? r.Portfolio : null ,
DataType = groupByDataType ? r.DataType : null ,
BucketName = groupByBucketName ? r.BucketName : null ,
ChildPortfolio = groupByChildPortfolio ? r.ChildPortfolio : null
}
into gg
select new DecisionSupportData
{
Portfolio = gg.Key.Portfolio,
DataType = gg.Key.DataType,
BucketName = gg.Key.BucketName,
ChildPortfolio = gg.Key.ChildPortfolio
}
).ToList();

Categories