Dapper only returns Null values - mysql

I am facing a problem using Dapper.
I have two models:
public class ClientEventsModel
{
public int Id { get; set; }
public int ClientId { get; set; }
public ClientEventTypeLog EventType {get; set;}
public int Value { get; set; }
public DateTime Date { get; set; }
public string? Doer { get; set; }
}
[Serializable]
public class ExtentedClientEventsModel : ClientEventsModel
{
public List<string> Values { get; set; } = new List<string>();
}
One is inherited from the other.
And a request in the form:
var sqlStr = $#"SELECT ce.Id, ce.ClientId, ce.EventType, ce.Value, ce.Date, a.UserName AS Doer, cevn.`Values` FROM clients.client_events ce
LEFT JOIN `z-price`.aspnetusers a ON ce.Doer = a.Id_num
LEFT JOIN clients.clients_events_value_name cevn ON ce.Id = cevn.ClientEventsId
where ClientId = {clientId} and Date BETWEEN '{from.ToMysql()}' and '{to.AddDays(1).ToMysql()}'";
var result = DefaultConnection.Query<ExtentedClientEventsModel>(sqlStr);
When I execute the query in the client it returns 16 records. But when I use Dapper it returns 4 records. And only those with the Doer == null field.
I tried replacing the model with a dynamic type, but it didn't help.

Dapper doesn't get to invent the number of rows coming back. If Dapper says there were 4 rows, then one of two things:
you've found a niche edge case that hasn't been seen in the many years of Dapper
your query really does only return 4 rows
Now, I'm open to "1", but in reality "2" is much more likely. I suspect the real problem here is the parameters - or lack there-of. Never ever use concatenation to build SQL from values. Try instead:
const string sqlStr = #"
SELECT ce.Id, ce.ClientId, ce.EventType, ce.Value, ce.Date, a.UserName AS Doer, cevn.`Values` FROM clients.client_events ce
LEFT JOIN `z-price`.aspnetusers a ON ce.Doer = a.Id_num
LEFT JOIN clients.clients_events_value_name cevn ON ce.Id = cevn.ClientEventsId
where ClientId = #clientId and Date BETWEEN #from and #to";
var result = DefaultConnection.Query<ExtentedClientEventsModel>(
sqlStr, new { clientId, from, to = to.AddDays(1) }).AsList();
(note: different databases have different syntax for parameters; if #clientId etc doesn't work, try :clientId, $clientId, etc)

This is what the request gives in the DbForge client
And this is what Dapper returns:
at that

Related

How to convert SQL Server query to JSON

I need to build a table in a view using the result of this SQL Query
SELECT f.empresaid,
e.fantasia AS Empresa,
f.filialid,
f.fantasia AS Filial,
u.consultorid AS ConsultorID,
cs.nome AS Consultor,
'' AS Midia,
fp.campoextra,
Count(DISTINCT p.usuarioid) AS Total,
Count(DISTINCT u.ativacao) AS TotalAtivos,
Iif(Count(DISTINCT p.usuarioid) > 0, ( Cast(
Count(DISTINCT u.ativacao) AS DECIMAL) / Count(DISTINCT p.usuarioid) ), 0
) * 100
AS Porcentagem
FROM formas_pagamento fp
INNER JOIN usuarios u
ON u.forma_pagamentoid = fp.forma_pagamentoid
INNER JOIN pagamentos p
ON p.usuarioid = u.usuarioid
AND p.tipo = 'MTU'
INNER JOIN cartoes c
ON c.usuarioid = u.usuarioid
AND c.dependenteid = 0
INNER JOIN midias m
ON m.descricao = u.midia
INNER JOIN consultores cs
ON cs.consultorid = u.consultorid
INNER JOIN filiais f
ON f.filialid = u.filialid
INNER JOIN empresas e
ON e.empresaid = f.empresaid
WHERE c.dependenteid = 0
AND u.cadastro > '2019-07-01'
AND u.cadastro < '2019-08-01'
AND u.filialid = 3
GROUP BY f.empresaid,
e.fantasia,
f.filialid,
f.fantasia,
u.consultorid,
cs.nome,
fp.campoextra
ORDER BY empresaid,
filialid,
consultor,
campoextra
Which gives me this result, the table in the view should be created with the structure as follows table structure and organization. I was trying to load this query data directly from my ViewModel List but that went heavy, if I could have a json array as following : JSON I could build the table with that desired structure more easily, can anyone help ? Thanks !
----------------------------------EDIT-------------------------------------
public List<ViewModelOrigemEConsultor> GetConsultorOrigem ()
{
var Lista = new List<ViewModelOrigemEConsultor>();
/*string SQL = SQL QUERY GOES HERE */
var cnn = CnnDB.OpenDB();
using (cnn)
{
var cmd = new SqlCommand(SQL, cnn);
cnn.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
decimal Porcentagem = 0;
while (reader.Read())
{
Porcentagem = (decimal)(Convert.ToInt32(reader["TotalAtivos"]) / Convert.ToInt32(reader["Total"]));
Lista.Add(new ViewModelOrigemEConsultor
{
EmpresaID = Convert.ToInt32(reader["EmpresaID"]),
Empresa = reader["Empresa"].ToString(),
FilialID = Convert.ToInt32(reader["FilialID"]),
Filial = reader["Filial"].ToString(),
ConsultorID = Convert.ToInt32(reader["ConsultorID"]),
Consultor = reader["Consultor"].ToString(),
Midia = reader["Midia"].ToString(),
FormaPagamento = reader["FormaPagamento"].ToString(),
Total = Convert.ToString(string.Format("{0:N}", reader["Total"])),
TotalAtivos = Convert.ToString(string.Format("{0:N}", reader["TotalAtivos"])),
Porcentagem = Convert.ToString(string.Format("{0:N}", Porcentagem))
});
};
}
};
return Lista;
}
MODEL
public class ViewModelOrigemEConsultor
{
public int EmpresaID { get; set; }
public string Empresa { get; set; }
public int FilialID { get; set; }
public string Filial { get; set; }
public int ConsultorID { get; set; }
public string Consultor { get; set; }
public string Midia { get; set; }
public string FormaPagamento { get; set; }
public string Total { get; set; }
public string TotalAtivos { get; set; }
public string Porcentagem { get; set; }
}
If you've got the list of objects populated and are just looking to convert it to JSON simply use something like https://www.nuget.org/packages/Newtonsoft.Json and then serialize the list to json. In this case it would be similar to:
var json = JsonConvert.SerializeObject(model);

Need help in solving SQL

I am new in Asp.net
now i want to try to start a social network project
I have 3 tables
User
Userid
-Username
-Email
-Password
-Name
-Profilepic
Post
-Postid -Content -Postdate -Userid
Friendlist
Friendlistid - userid - friendid -status
i want to load the post that from my friend and myself
This is my sql code
select b.userid, a.Friendid, c.name, b.postid, b.Content, b.postdate, c.profilepic
from friendlist a
left join [user] c on a.friendid = c.userid
left join post b on a.friendid = b.userid
where a.userid = 1 AND a.Status = 1 OR a.Userid = 1
ORDER BY postid desc
The problem that i faced was my post will repeat
For example, my friendlist table has 3 friends, my every single post will repeat 3 times and my friend post stay normal.
Any solution for this sql code?
If you have a relationship between the tables and are using Entity Framework. You can simply invoke the tables below its "friendlist". You can take this query return creating a class specific to this return
public class ListFriendsGroup
{
public int UserId { get; set; }
public int friendId { get; set; }
public int PostId{ get; set; }
public string Name { get; set; }
public string Content { get; set; }
public DataTime PostData { get; set; }
public string ProfilePic { get; set; }
}
var friendlist = Context.friendList.Include("user").Include("post")
// HERE .GroupBy(...
.Select(f => new ListFriendsGroup() { Userid = f.post.userid, FriendId = f.Friendid, Name = f.user.name, PostId = f.post.postid, Content = f.post.Content, PostData = f.post.postdate, Profilepic = f.user.profilepic }).ToList()
Read about the Group By clause to perform grouping of data
Group by, Count and Lambda Expression

PetaPoco is mapping 0 for every Id in my object?

I have the following object:
public class VehicleMake
{
[Column(Name = "MakeID")]
public int Id { get; set; }
public string Name { get; set; }
}
To get a list of vehicle makes, I am doing the following:
var vehicleMakes = _db.Fetch<VehicleMake>(#"SELECT DISTINCT(m.MakeID) AS Id, m.Name
FROM vehicles v
INNER JOIN makes m on m.MakeID = v.Make
WHERE [Year] = #year
ORDER BY m.Name", new { year });
When I run the SQL in SSMS, it returns the correct data, but in VS, it is mapping 0 for every Id property.
Ah, I got it, in case anyone else runs into the problem. Since I am doing:
SELECT DISTINCT(m.MakeID) as Id..., there is no reason to have:
[Column(Name = "MakeID")] since I am aliasing the column as Id already.

mapping a linq to sql view result to entities - how to change the group by clause?

Assume that I have a very simple db diagram:
and a view for it:
create view vTraining
as
select t.Id as TrainingId,t.[Status] ,
t.[User], t.Title,t.Organisation,t.[Month],t.[Year],
s.Id as SubjectId, s.Name as SubjectName,
c.Text as Comment
from Training t
join Subject s on s.Training = t.Id
join Comment c on c.Training = t.Id
with sample data:
As you can see, this is a single training with three subjects.
I want to map this result to this structure by linq to sql:
public class ViewModel
{
public string Comment { set; get; }
public List<Item> Trainings { set; get; }
}
public class Item
{
public int TrainingId { set; get; }
public int User { set; get; }
public int Status { set; get; }
public string Title { set; get; }
public string Organisation { set; get; }
public int? Month { set; get; }
public int Year { set; get; }
public List<KeyValuePair<int, string>> Subjects { set; get; }
}
This is my query, that I created:
var data = (from training in dc.vTrainings
group training by new
{
training.TrainingId,
training.Status,
training.Month,
training.Organisation,
training.Title
}
into g
select new ViewModel()
{
Comment = g.Select(x =>
x.Comment).First(),
Trainings = g.Select(
x => new Item()
{
Month = x.Month,
Organisation = x.Organisation,
Title = x.Title,
Year = x.Year,
Subjects = g.Select(
z => new KeyValuePair<int, string>(z.SubjectId, z.SubjectName)).ToList()
}).ToList()
})//.GroupBy(x => x.Trainings).Select(x => x.Key)
.ToList();
Unfortunatelly the result I get is not the one I want:
The ViewModel object is created only ones what is ok, but for each single subject, the new Item is created (should be one). The Subjets list is created correctly. I tried to create a second group by, and some other things, but this is the best result I can get for now.
How to write this query to get one ViewModel object which has one Item object with three subjects?
I finally got my the proper result:
var data = (from g in
(from training in dc.vTrainings
where training.Status ==1
group training
by new
{
training.TrainingId,
training.Status,
training.Month,
training.Organisation,
training.Title
}
into g
select g).AsEnumerable()
select new ViewModel()
{
Comment = g.Select(x =>
x.Comment).FirstOrDefault(),
Trainings = g.GroupBy(x => x.Status).Select(
x => new Item()
{
Month = g.Key.Month,
Organisation = g.Key.Organisation,
Title = g.Key.Title,
Subjects = (from i in g select new KeyValuePair<int, string>(i.SubjectId, i.SubjectName)).ToList()
}).ToList()
}).ToList();
This query works only for one training, but for me this is not a problem, because I filtering it by the newest status. Still I'm curious how to write it for more than one training.
Try this:
var trainings =
dc.vTrainings
.GroupBy(
t => new
{
t.TrainingId,
t.Status,
t.Month,
t.Organisation,
t.Title,
t.User,
t.Year
},
t =>
new
{
t.SubjectId,
t.SubjectName
})
.ToList()
.Select(
t =>
new Item
{
TrainingId = t.Key.TrainingId,
Status = t.Key.Status,
Month = t.Key.Month,
Organisation = t.Key.Organisation,
Title = t.Key.Title,
User = t.Key.User,
Year = t.Key.Year,
Subjects =
t.Select(s => new KeyValuePair<int,string>(s.SubjectId,s.SubjectName)).ToList()
});

LINQ to SQL - Searching column of joined table

I am trying to return a result set that includes rows where any of three strings has a string match. My domain models look like this:
public class Customers
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class BidNames
{
public int BidNameID { get; set; }
public int CustomerID { get; set; }
public string BidName { get; set; }
}
There is a FK between BidName.CustomerID and Customers.CustomerID and it is a one-to-many relationship where there can be multiple BidNames for a single Customer. When searching my customer table I want to bring back all records where there is a string match in FirstName, LastName or any of the associated BidNames. For this example I'll use a BidName search string of "ba".
from c in Customers
where c.FirstName.Contains("ba") || c.LastName.Contains("ba") || c.BidNames.Any(b=>BidNames.BidName.Contains("ba"))
orderby c.LastName, c.FirstName
select new { CustomerID = c.CustomerID, FirstName = c.FirstName, LastName = c.LastName }
It all works until I add the final criteria in the Where clause. I understand that c.BidNames is a collection and I'm looking to see if Any of them have a BidName that contains "ba". Where I'm running into trouble is trying to specify the BidNames.BidName column to search for the string. The code I've written above fails with "BidNames does not contain a definition for 'BidName'"
How do I write the last part of the Where clause so I can search all the BidNames.BidName fields associated with the Customer record? I hope and assume I can use the same syntax to specify the BidName field in the orderby and select clauses as well.
Many thanks,
BK
FINAL ANSWER:
from c in Customers
where
c.FirstName.Contains("ba") ||
c.LastName.Contains("ba") ||
c.BidNames.Any(b=>b.BidName.Contains("ba"))
orderby
c.LastName,
c.FirstName
select new {
CustomerID = c.CustomerID,
FirstName = c.FirstName,
LastName = c.LastName,
BidNames = c.BidNames.OrderBy(b=>b.BidName)
}
Try changing your where clause to
Where c.FirstName.Contains("ba") ||
c.LastName.Contains("ba") ||
c.BidNames.Any(b=>b.BidName.Contains("ba"))
In your Any clause, b is an instance of the BidNames class, so you want to access properties of that rather than the BidNames property of the Customer.