FX_RATE field is null in some cases. I am getting this error though I am using isDBNUll to replace null as 0.
Cannot cast DBNull.Value to type 'System.Decimal'. Please use a nullable type.
Dim query =
From tl_ancDT In dtReportData.AsEnumerable
Group Join tl_prcDT In dtPostedFlag.AsEnumerable On tl_ancDT.Field(Of String)("ENTITY") Equals tl_prcDT.Field(Of String)("ENTITY") And
tl_ancDT.Field(Of String)("ACCOUNT") Equals tl_prcDT.Field(Of String)("ACCOUNT") And
tl_ancDT.Field(Of String)("TRANSACTION_BATCH_ID") Equals tl_prcDT.Field(Of String)("TRANSACTION_BATCH_ID")
Into tl_ancDT_tl_prcDT = Group
From tl_prcDT In tl_ancDT_tl_prcDT.DefaultIfEmpty()
Select New With {
Key .ENTITY = tl_ancDT.Field(Of String)("ENTITY"),
Key .ACCOUNT = tl_ancDT.Field(Of String)("ACCOUNT"),
Key .STATUS = tl_ancDT.Field(Of String)("STATUS"),
Key .ACTIVITY_NUMBER = tl_ancDT.Field(Of String)("ACTIVITY_NUMBER"),
Key .TRANSACTION_BATCH_ID = tl_ancDT.Field(Of String)("TRANSACTION_BATCH_ID"),
Key .ENTERED_CURRENCY = tl_ancDT.Field(Of String)("ENTERED_CURRENCY"),
Key .OPENING_BALANCE = tl_ancDT.Field(Of Decimal)("OPENING_BALANCE"),
Key .FX_RATE = If(IsDBNull(tl_ancDT.Field(Of Decimal)("FX_RATE")),0, tl_ancDT.Field(Of Decimal)("FX_RATE")),
Key .CLOSING_BALANCE = tl_ancDT.Field(Of Decimal)("CLOSING_BALANCE"),
Key .POSTEDFLAG = If(tl_prcDT Is Nothing,String.Empty , tl_prcDT.Field(Of String)("POSTEDFLAG"))
}
Ragav.
Related
I have a query which works fine in SQL but I can't seem to create the equivalent in JPA. The CriteriaBuilder "or" doesn't appear to execute an "or".
These are the tables ...
Table A
id : Long : primary key
b_id : Long : foreign key to id of Table B
c_id : Long : foreign key to id of Table C
Table B
id: Long : primary key
loc_id: Long
Table C
id: Long : primary key
d_id : Long : foreign key to id of Table D
Table D
id: Long : primary key
loc_id: Long
This is the data in the tables (in order of the fields listed) ...
Table A:
1, 1, null
2, 2, null
3, null, 1
Table B:
1, 5
2, 6
Table C:
1, 1
Table D:
1, 5
And my sql query finds all the records in table A where the loc_id is 5 in Table B or Table D via the foreign keys. (2 results - row id 1 and row id 3)
select * from A
LEFT JOIN B on B.id = a.b_id
LEFT JOIN C on C.id = a.c_id
LEFT JOIN D on D.id = c.d_id
WHERE B.loc_id = 5 or D.loc_id = 5
However I am struggling to code in JPA the same results.
I have tried below which creates 2 predicates which both find 1 record when executed individually but when I "or" them it produces 0 records. How can that be right?
EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
Root<A> rt = cq.from(A.class);
List<Predicate> predicates = new ArrayList<>();
Join<B, A> join1 = rt.join("b_id", JoinType.INNER);
Join<C, A> join2 = rt.join("c_id", JoinType.INNER);
Join<D, C> join3 = join2.join("d_id", JoinType.INNER);
predicates.add(cb.or(cb.equal(join1.get("loc_id"), 5), cb.equal(join3.get("loc_id"), 5)));
CriteriaQuery x = cq.select(rt).where(predicates.toArray(new Predicate[predicates.size()]));
Query q = em.createQuery(x);
List<A> = q.getResultList();
All suggestions gratefully accepted, thanks ....
Here is solution
EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<A> cq = cb.createQuery(A.class);
Root<A> rt = cq.from(A.class);
Join<B, A> joinB = rt.join("b_id", JoinType.LEFT);
Join<C, A> joinC = rt.join("c_id", JoinType.LEFT);
Join<D, C> joinD = joinC.join("d_id", JoinType.LEFT);
Predicate bPredicate = cb.equal(joinB.get("loc_id"), 5);
Predicate dPredicate = cb.equal(joinD.get("loc_id"), 5);
Predicate predicate = cb.or(bPredicate, dPredicate);
CriteriaQuery<A> x = cq.select(rt).where(predicate);
TypedQuery<A> q = em.createQuery(x);
List<A> result = q.getResultList();
enter image description here
How can I get Rank of a user in table by LINQ ? I use VB.NET CODE
if we have these fields in our table
[id , name , score]
after order by score of users how we can get the ranking ( row number ) one of them in our query ?
Thank you man . I used the bellow code and it's work fine for me:
Dim query = (From P In DB.tblUserScores Order By P.Score
Descending Select P).AsEnumerable()
Dim Rank As Integer = 1
For Each userObj As tblUserScore In query
If userObj.DeviceId = DeviceID Then Exit For
Rank += 1
Next
Here's how:
Dim records = _
{ _
New With { Key .ID = 1, Key .Name = "A1", Key .Score = 7 }, _
New With { Key .ID = 2, Key .Name = "A2", Key .Score = 9 }, _
New With { Key .ID = 3, Key .Name = "A3", Key .Score = 2 }, _
New With { Key .ID = 4, Key .Name = "A4", Key .Score = 1 }, _
New With { Key .ID = 5, Key .Name = "A5", Key .Score = 6 }, _
New With { Key .ID = 6, Key .Name = "A6", Key .Score = 4 }, _
New With { Key .ID = 7, Key .Name = "A7", Key .Score = 7 }, _
New With { Key .ID = 8, Key .Name = "A8", Key .Score = 3 }, _
New With { Key .ID = 9, Key .Name = "A9", Key .Score = 5 }, _
New With { Key .ID = 10, Key .Name = "A10", Key .Score = 8 } _
}
Dim query = _
From r In Records _
Order By r.Name Ascending
Order By r.Score Descending
Select r
query.Dump()
Dim rank = _
query _
.Select(Function (x, n) New With { Key .Record = x, Key .Rank = n + 1 }) _
.ToDictionary(Function (x) x.Record.Name, Function (x) x.Rank)
Dim name = "A9"
Console.WriteLine("User " & name & "'s Rank is " & rank(name))
That gives me:
User A9's Rank is 6
Yesterday I asked this question on stackoverflow. Today I realize that if I do a GROUP BY I also need to create a new type of object.
Let's say I have some data that looks like this:
var1 var2 var3 qty
1 a 1a 50
1 a 1a 25
2 b 2b 10
2 b 2b 15
2 b 2b 10
3 a 3a 25
Here is my working LinQ query
From j In MyTable
Where j.var1 = "xxx"
Group j By Key = New With {Key .var1 = j.var1, Key .var2= j.var2, Key .var3 = j.var3} Into Group
Select New With {.var1 = Key.var1, .var2 = Key.var2, .var3 = Key.var3, .qty = Group.Sum(Function(x) x.qty)}
Actually I use Entity Framework and the code look more like this
Dim foo = (From j In dbContext.MyTable
Where j.var1 = anotherVariable
Group j By Key = New With {Key .var1 = j.var1, Key .var2= j.var2, Key .var3 = j.var3} Into Group
Select New With {.var1 = Key.var1, .var2 = Key.var2, .var3 = Key.var3, .quantity = Group.Sum(Function(x) x.Qty)}).ToArray()
foo is a new type that doesn't exist in my generated Entities. But I have an entity generated by my entity framework that can contains these. It's MyTable itself. I use a GROUP BY only to sum a column of MyTable. I query a MyTable entities and I can put the result in a MyTable entity too.
My question are
1) Can I write something like this
Dim foo = (From j In dbContext.MyTable
Where j.var1 = anotherVariable
Group j By Key = New With {Key .var1 = j.var1, Key .var2= j.var2, Key .var3 = j.var3} Into Group
Select New MyTable With {.var1 = Key.var1, .var2 = Key.var2, .var3 = Key.var3, .qty = Group.Sum(Function(x) x.qty)}).ToArray()
In this case do I need to explicitely write all the mappings ?
2) Should I change my mind. Do a simpler query without GROUP BY and try to group and sum in a VB.NET loop (For Each). Or two queries ? On to get all MyTable with a WHERE clause and another to group ?
Dim foo = dbContext.MyTable.Where(Function(p As MyTable) p.var1 = anotherVariable).ToArray()
For Each bar In foo
'Code to group and sum or another query
Next
You won't be able to instantiate MyTable in an LINQ to Entities query but you can simply enumerate the results of the projection with ToArray and then construct the entities with another Select call.
I am trying to perform this query on two DataTables in a DataSet
SELECT Totals.accCategory, Totals.ID, Totals.Account, Sum(Totals.Jan) AS Jan FROM (SELECT * FROM Allocated UNION SELECT * FROM Spent) AS Totals GROUP BY Totals.accCategory, Totals.ID, Totals.Account
As they are generated in code (in memory) into the DataSet I need to use LINQ thus:
Dim t = (From totals In (allocated.AsEnumerable.Union(spent.AsEnumerable)) _
Group totals By accCategory = totals.Item("accCategory"), ID = totals.Item("ID"), Account = totals.Item("Account") _
Into g = Group _
Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = g.Sum(Function(totals) Totals.Item("Jan"))}).ToList
Which fails as there are some instances where there are no records to sum. The Access query returns an empty cell - which is what I want. I can make the LINQ statement work by using If(IsDbNull(totals.Item("Jan")),0,totals.Item("Jan")) but then I get 0.00 if the total is zero (which is correct) but also if there are no items to sum (which I don't want)
I have tried Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = g.Sum(Function(totals) DirectCast(totals.Item("Jan"), Nullable(Of Decimal)))}).ToList which doesn't work either.
How can I make .Jan a Nullable(Of Decimal) and accept DBNull as a value??
Thanks
Andy
Got it!
Dim t = (From totals In (allocated.AsEnumerable.Union(spent.AsEnumerable)) _
Group totals By accCategory = totals.Item("accCategory"), ID = totals.Item("ID"), Account = totals.Item("Account") _
Into g = Group _
Select New With {Key .accCategory = accCategory, Key .ID = ID, Key .Account = Account, Key .Jan = If(g.AsQueryable.Any(Function(totals) totals.Field(Of Nullable(Of Decimal))("Jan").HasValue), g.AsQueryable.Sum(Function(totals) totals.Field(Of Nullable(Of Decimal))("Jan")), Nothing)}).ToList
I am stumped. I need help. I have a DTO object with duplicates patient address data. I need to get only the unique addresses.
Dim PatientAddressDto = New List(Of PatientAddress)
{Populate PatientAddressDto with lots of duplicate data}
PatientAddressDto = (From d In PatientAddressDto
Group d By PatientAddressDtoGrouped = New PatientAddress With {
.Address1 = d.Address1,
.Address2 = d.Address2,
.City = d.City,
.State = d.State,
.Zip = d.Zip
}
Into Group
Select New PatientAddress With {
.Address1 = PatientAddressDtoGrouped.Address1,
.Address2 = PatientAddressDtoGrouped.Address2,
.City = PatientAddressDtoGrouped.City,
.State = PatientAddressDtoGrouped.State,
.Zip = PatientAddressDtoGrouped.Zip
}).ToList()
I have tried the following with no luck:
PatientAddressDto = (From d In PatientAddressDto
Select New PatientAddress With {
.Address1 = d.Address1,
.Address2 = d.Address2,
.City = d.City,
.State = d.State,
.Zip = d.Zip
}).Distinct
and also
PatientAddressDto = PatientAddressDto.GroupBy(Function(p) New PatientAddress With {
.Address1 = p.Address1,
.Address2 = p.Address2,
.City = p.City,
.State = p.State,
.Zip = p.Zip
})
You can use an anonymous type and make use of the Key keyword in order for equality to behave the way you expect (not required for C#).
Change your grouping by specifying the Key prefix and remove the PatientAddress usage :
Group d By PatientAddressDtoGrouped = New With {
Key .Address1 = d.Address1,
Key .Address2 = d.Address2,
Key .City = d.City,
Key .State = d.State,
Key .Zip = d.Zip
}
I have found the following code to work which essentially accomplishes the grouping that I desire and populating the new object as type PatientAddress therefore eliminating the use of anonymous objects and the keyword Key.
Maybe someone can explain it, at the moment I can not. Have a nice day.
Dim PatientAddressDto = New List(Of PatientAddress)
{Populate PatientAddressDto with lots of duplicate data}
PatientAddressDto = (From d In PatientAddressDto
Group d By d.Address1,
d.Address2,
d.City,
d.State,
d.Zip Into g =
Group Let grp = New PatientAddress With {.Address1 = Address1,
.Address2 = Address2,
.City = City,
.State = State,
.Zip = Zip}
Select grp).ToList()
Its probably because PatientAddress does not override GetHashCode and Equals.
An alternative is to us an anonymous type for the grouping. Try writing:
Group d By PatientAddressDtoGrouped = New With { Key .Address1 = d.Address1, ....