How do I used Count(*) with DAL2? - c#

I want to get counts for various groupings of data in some of my tables and am not sure if it is possible using DAL2.
I want perform queries such as:
SELECT DISTINCT productType, COUNT(*) FROM Products GROUP BY productType
The information I come across only includes examples that allow the user to specify the WHERE part of the SQL. This example unfortunately skirts right around the WHERE part of the query so I am not sure how I should approach this using DAL2. Is it possible using DAL2 or do I need to query the database another way? If it can be done using DAL2, how do I execute such a query?

The examples showing only the WHERE part mean that PetaPoco fills in the "SELECT * FROM TableName" part for you, but of course you can execute your own sql statement
In your case:
public class ProductCount {
public int ProductType {get; set;}
public int Count {get; set;}
}
var ProductCountList = db.Fetch<ProductCount>(#"SELECT DISTINCT productType,
COUNT(*) as Count
FROM Products
GROUP BY productType");

I can't tell you what is best practice. But I have a SQL server back end and use dal2 with a dnn module. I just created a view in SQL server with my grouping and joins and then mapped that view like a table (use view name instead of table name in the class annotations) with an auto increment of false. Worked for me and I get the benefit of precompiled and non dynamic queries. If you need to generate this dynamically, I am not sure what the best approach is.
I would love to hear from other members about this.

Related

Dapper incorrectly thinking Column Numeric

I have been using dapper for a while but have come across a strange issue.
I have a Column in a database table called , in my query my Table
my dapper query is
SELECT p.Id PaymentId, p.AmountPaid PaymentAmountPaid, np.NoticeNo PaymentRef
In the Database the column NoticeNo is defined as nchar
When I query it, its mapped to class with the following property
public string PaymentRef { get; set; }
I query as follows connection.Query<PaymentSummary>(sqlStr)
but very strange, dapper seems to think that the NoticeNo column is a number, so if the store notice no as 1234 then when its queried the result is 1234.00
Most of the notice numbers are numeric, but they don't have to be.
Any ideas?
Thanks ash.
Turns out it wasn't Dapper's Fault. The query was part of a union, and I had the notice no and the amount column in a different order in two if the queries, which was forcing the result to be a Number!!

Insert row to any table with LINQ

I want to develop a dynamic insert method with LINQ.
Let's assume I have two tables like:
Product
{
id int,
name varchar(20),
price int
}
Factory
{
id int,
name varchar(50),
address varchar(240)
}
But, consider that I don't know the tables, but only the names of them.
This is how I get the column names of the table which I know the name of:
var db = new DataContext();
var columnNames = db.Mapping.MappingSource
.GetModel(typeof(DataContext))
.GetMetaType(typeof(table_name))
.DataMembers;
But I can't figure out how to get the column names of the table which I don't know the name of. What I tried so far:
context.Mapping.GetTables().FirstOrDefault(
x=> x.TableName == table_name ).Model.ContextType.Attributes;
table_name is dynamically changes and be like: Product, Factory etc.. But this way is a dead end, I think.
So, in the end I couldn't figure out how to get column names of a random table, let alone inserting a row to random table.
I can do this with classic way using SqlCommands but I want to know how to do it with LINQ.
As Mant101 said in his comment:
I don't think Linq is going to help here. You could write some code in
ADO.NET to get the columns definitions from the database, then use
some reflection to build an insert/update statement based on the
properties of the object that match the columns. I would ask why you
need to do this, are you working with some database that is in an
unknown state when the app run?
And as StriplingWarrior gives countenance to him with:
Mant101 is right: The whole purpose of an object-relational mapper is
to make it easier to work with persisted data by converting it into
objects that you can use in the programming language. Since you're not
going to program against those objects in this case, you don't get any
value from LINQ-to-SQL. You're better off bypassing the ORM and using
straight SQL/ADO.NET.
Inserting any table using generic methods with LINQ seems impossible.
However, you can do it with SQL.

Using Dapper to populate objects from a T-SQL View

I'm trying out using Dapper for my data access (in ASP.NET MVC3 FWIW). I have a a T-SQL view (in SQL Server) which is something like this:
SELECT s.*, c.CompanyId AS BreakPoint c.Name AS CompanyName
FROM tblStaff AS s
INNER JOIN tblCompanies AS c ON c.CompanyId = s.CompanyId
So pretty simple. Essentially a list of staff each of which have a single company.
The problem I'm having is that I'm trying to map the output of this query onto my POCOs, but because each field in the View has to be unique (i.e. CompanyName instead of Name which already exists in tblStaff) the mapping to POCOs isn't working.
Here's the code:
var sql = #"select * from qryStaff";
var people = _db.Query<Person, Company, Person>(sql, (person, company) => {person.Company = company; return person;}, splitOn: "BreakPoint");
Any advice how I might solve this puzzle? I'm open to changing the way I do views as right now I'm stumped about how to progress.
You should explicitly list all the fields returned from you view (no asterisks!) and where the field names are not unique, make use of aliases to deduplicate. As an exmaple:
SELECT
s.CompanyName as CompanyName1,
s.BreakPoint as BreakPoint1,
...
c.CompanyId AS BreakPoint,
c.Name AS CompanyName
FROM tblStaff AS s
INNER JOIN tblCompanies AS c ON c.CompanyId = s.CompanyId
The fields listed and the aliases you might use depend, of course, entirely on your code. Typically you adjust the aliases in your query to match the property names of the POCO.
Also, as a general rule of thumb, it's good to stay away from wildcards in SQL queries exactly because issues like this are introduced. Here's a decent article on SQL query best practices.
Excerpt:
Using explicit names of columns in your SELECT statements within your
code has a number of advantages. First, SQL Server is only returning
the data your application needs, and not a bunch of additional data
that your application will not use. By returning only the data you
need you are optimizing the amount of work SQL Server needs to do to
gather all the columns of information you require. Also by not using
the asterisk (*) nomenclature you are also minimizing the amount of
network traffic (number of bytes) required to send the data associated
with your SELECT statement to your application.
Additionally by explicitly naming your columns, you are insulating
your application from potential failures related to some database
schema change that might happen to any table you reference in your
SELECT statement. If you were to use the asterick (*) nomenclature and
someone was to add a new column to a table, your application would
start receiving data for this additional column of data, even without
changing your application code. If your application were expecting
only a specific number of columns to be returned, then it would fail
as soon as someone added an additional column to one of your
referenced tables. Therefore, by explicitly naming columns in your
SELECT statement your application will always get the same number of
columns returned, even if someone adds a new column to any one of the
tables referenced in your SELECT statement.

Is there any way to get the table hierarchy from a connection string in c#?

I have a current requirement to determine the table hierarchy from a sql statement within c#. For example, consider the following sql statement:
Select Table1.*, Table2.* from Table1
left join table2 on Table1.parentCol = Table2.childCol
That might return 7 columns, 3 for Table1 and 4 for table2. I need to know the column names, and ideally (though not mandatory) their types.
I have no control over what SQL Statement will be used, as this is a user entered field. In C# it's a very basic task to open a connection and create an SqlCommand using that statement. I have freedom to run the SQL into a SqlDataReader, or any other System.Data.SqlClient class if necessary, however I cannot find any combination that will return the columns, rather than the actual column values.
Is anyone able to help?
Many thanks and best regards
You cannot do what you are asking (easily).
More to the point, do not let users enter arbitrary TSQL (You will regret it at some point...).
Instead, create a 'Search' form that allows entering various params and use a parameterised query onto a view that joins all the tables/columns required.
There's no direct way. You'll need to parse names of all the tables from the sql query.
Once you have done that you'll need to write few queries on Information_Schema to get raw data for what you are looking for.
If you are on SQL Server, you may want to use Catalog View
ex-
Select * from sys.tables where [Name] = 'MyTable'

How do IN () statements work in NHibernate? (Using Criteria)

I'm trying to create the equivalent of the below using NHibernate. I've done all the mappings using fluent and I can do the basic queries just fine but I have no idea how to do this.
-**Product Table**
Reference
Title
Subjects (Many to Many relationship)
Price
-**Subject table**
SubjectID
Name
-**SubjectToProductMapping Table**
Reference
SubjectID
Now I need to do this:
SELECT *
FROM Product
WHERE Reference IN
(Select Reference FROM SubjectToProductMapping WHERE SubjectID = #SubjectID)
Baring in mind the Product table has been simplified a great deal for the post and that I would prefer to use an IN statement to keep the rest of the query simpler. I would ideally like to create the query using Criteria becuase I will be using Criteria to page the results.
Thanks in advance
Why would you use an in when a join would suffice? provided your Products class has a mapped collection of subjects then you could just use this Criteria
IList<Product> results = session.CreateCriteria(typeof(Product))
.CreateCriteria("Subjects", JoinType.Join)
.Add(Resitctions.Eq(Projections.ID, subjectID))
.List<Product>();

Categories