Multimapping in Dapper Without Custom SQL - dapper

Is there a way to use multimapping in Dapper in a generic way, without using custom SQL embedded in C# code?
See for example
Correct use of Multimapping in Dapper
Is there a generic way to query the data from 2 related entities, where common fields are determined automatically for join?

Don't do this. Don't even think this way! Databases are long lasting and normalized. Objects are perishable and frequently denormalized, and transitioning between the two is something to do thoughtfully, when you're writing your SQL. This is really not a step to automate. Long, painful experience has convinced many of us that database abstractions (tables and joins) should not just be sucked into (or generated out of) code. If you're not yet convinced, then use an established ORM.
If, on the other hand, you absolutely want to be in control of your SQL, but its the "embedding" in string literals in C# that bugs you, then I couldn't agree more. Can I suggest QueryFirst, a visual studio extension that generates the C# wrapper for your queries. Your SQL stays in a real SQL file, syntax validated, DB references checked, and at each save, QueryFirst generates a wrapper class with Execute() methods, and a POCO for the results.
By multi-mapping, I presume you want to fill a graph of nested objects. A nice way to do this is to use one QueryFirst .sql per class in your graph, then in the partial class of the parent, add a List of children. (QueryFirst generated POCOs are split across 2 partial classes, you control one of them, the tool generates the other.)
So, for a graph of Customers and their orders...
In the parent sql
select * from customers where name like #custName
The child sql
select * from orders where customerId = #customerId
In the parent partial class, for eager loading...
public List<Orders> orders;
public void OnLoad()
{
orders = new getOrders().Execute(customerId); // property of the parent POCO
}
or for lazy loading...
private List<Orders> _orders;
public List<Orders> orders
{
get
{
return _orders ?? _orders = new GetOrders().Execute(customerId);
}
}
5 lines of code, not counting brackets, and you have a nested graph, lazy loaded or eager loaded as you prefer, the interface discoverable in code (intellisense for the input parameter and result). Their might be hundreds of columns in those tables, whose names you will never need to re-type, and whose datatypes are going to flow transparently into your C#.
Clean separation of responsibilities. Total control. Disclaimer : I wrote QueryFirst :-)

Multimapping with Dapper is a method of running multiple SQL queries at once and then return each result mapped to a specific object.
In the context of this question, Multimapping is not even relevant, re: you're asking for a way to automatically generate a SQL query from the given objects and creating the correct joins which would result in a single SQL query which is not related to Multimapping.
I suspect what you're looking for is something along the lines of the Entity Framework. There are a couple of Dapper extension projects you may want to look into which will generate some of your SQL. See: Dapper.Rainbow VS Dapper.Contrib

Related

How to use Difference function in EntityFrameworkCore?

I have this query to be executed :
Select * From Products WHERE Title like '%search text%'
ORDER BY Difference(Title, 'search text') DESC
Now I want to implement the above query using EntityFrameworkCore and linq.
So how can I call difference function to order products by closest match in Title column?
Every IQueryable holds an Expression and a Provider. The Expression holds the query that must be performed. The Provider knows who has to execute the query, usually a database management system. It is the task of the Provider to translate the Expression into the language that the database understands (something SQL-like) and to execute the query. The Provider will fetch the results in an efficient way and return the queried data as an enumerable object.
The IQueryable implements IEnumerable.
When you use LINQ functions like ToList(), FirstOrDefault(), Any(), or use the query in a foreach, then internally IEnumerable.GetEnumerator() is called and Enumerator.MoveNext()
This will order the Provider to translate the Expression into SQL and execute the query. The returned enumerable is used to enumerate over the returned items.
It is the task of the programmer of the class that implements the IQueryable to implement the translation of the Expression into SQL. This is not easy, and I think the people who created entity framework did a great job.
However, some items known in SQL are very difficult to implement. Among those are the notions of SoundEx and Difference. I'm not sure, but I think that one of the reasons that made this difficult is that they are typically something used in SQL, and not in any other kind of IQueryable systems.
In fact, there are a several functions that are not supported by entity framework. See Supported and unsupported LINQ methods (LINQ to entities).
Your DbContext is an abstract representation of your database model. Users of it should not care whether it uses Microsoft SQL, MySQL, or whether it is a data collection that doesn't use anything similar to SQL.
But if you are absolutely certain that it is okay to limit your DbContext to only a certain kind of databases, one that knows the concepts of SoundEx and Difference, consider creating a stored procedure for your query. See How to call a Stored Procedure in Entity Framework
SQL can not understand the Difference function written in c#. To make it work you will have to fetch values from Products table in a c# collection like List
Then do ordering on that list using Difference function

Is there any way to "name" or "tag" a LINQ query so that it can be identified by a tool like Ignite SQL easier?

Our team is moving towards LINQ, but one of the problems we've run up against is that you cannot easily identify where a LINQ query is coming from using tools like Ignite SQL.
Previously we have been using Stored Procedures, which are easy to track with Ignite. Find a problem Query, find the Stored Procedure that uses it, find the code that calls that Stored Procedure.
With LINQ, when a trouble Query shows up...we have no way to identify what is actually executing that code.
We are looking for a way to "tag" or "name" a LINQ query, so that we can better track our trouble queries back to code.
No, there is no way to do this. I would require a special command on top of the already leaky abstraction of IQueryable that EF implements. Something like db.Entities.Select(...).Name("Query1"). There are two alternatives (that I can think of).
By far the best option is to look at the query closely and try to reason it back to to point in the application it comes from. Why is this the best option? Because by doing this you gain insight in the kind of queries EF generates from which kind of LINQ statements. Soon you'll see a query and think ah, this must be a GroupBy, that must be an Any, etc. Together with the table and column names it should be possible to find the culprit.
The typical software developer's option, so inherently lazy and by definition not the best one: create a command interceptor that executes a special SELECT after EF's SQL commands.
using System.Data.Entity.Infrastructure.Interception;
...
public class StackTraceCommandInterceptor : DbCommandInterceptor
{
public override void ReaderExecuted(
DbCommand command,
DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
if (command.CommandText.StartsWith("SELECT"))
{
var cmd = command.Connection.CreateCommand();
cmd.CommandText = string.Format("SELECT '{0}'",
new System.Diagnostics.StackFrame(17));
cmd.ExecuteNonQuery();
}
}
}
And somewhere in your application startup:
DbInterception.Add(new StackTraceCommandInterceptor());
As you can see, after each SELECT command a new command is composed that SELECTs a text from nothing, so the only thing it does is make itself visible in any database profiling tool (it is not logged by EF's own logging, by the way). The text it logs is the 18th stack frame. From a bit of trial and error with EF's the current source this appeared to contain the method that executed the LINQ statement. Maybe with other versions it is different. If necessary you can output new System.Diagnostics.StackStrace(), i.e. the whole stack trace.
Needless to say that this interceptor should only be activated for diagnostic purposes.

Concept of a database driven program in VB.NET

I have been developing programs in VB.NET for a few years and am familiar with it. The area where I do not have a lot of exposure is databases.
I am writing a program (for my personal use) called movie manager. It will store information on movies I have. I have selected Sql Server Compact Edition database. Assume I have a database with two tables namely Info and Cast. Info table has a few columns such as movie_name, release_date and so on. Cast table has few cols such as first_name,last_name etc.
Right now I have created a DataSet which reads all the info of tables from database (opens connection, fills tables info, closes connection). This way in a global variable I have a snapshot of database.
My queries :
Once I have data with me, every time I need to add, edit or delete a record I have to open a connection, fire an sql and close the connection. Right ? Is there a way to do this without using Sql ? Plus is this concept okay.
Since I am not using structures so I need to create empty datasets to store temp information. Is this convenient ?
If I have to search for a specific thing in dataset table, then do I have to loop thru all items or can I use sql on dataset or is there an alternate ?
1)Once I have data with me, every time I need to add, edit or delete a record I have to open a connection, fire an sql and close the connection. Right ? Is there a way to do this without using Sql ? Plus is this concept okay.
No. To update a database, you have to use the database. Create a stored procedure in the database to handle your functionality and then call it from the code and pass in whatever data needs saved. DO NOT USE INLINE SQL. Paramterized stored procedures are the way to go.
2) Since I am not using structures so I need to create empty datasets to store temp information. Is this convenient ?
It depends on what you're doing. I would create an object model to retain my updated data and then I'd pass the properties into the stored procedure when it was time to save my changes.
3) If I have to search for a specific thing in dataset table, then do I have to loop thru all items or can I use sql on dataset or is there an alternate ?
You can loop the rows or you can use linq to pull what you need out. Linq is really nice as it's basically .NET coded queries against a collection.
There are plenty of tutorials/guides out there to show you how to update via stored proc call form your code. There are a ton of linq tutorials as well. Basically, a linq query against your table will look something like:
dim result as Generic.List(of String) =
(from r in table.AsEnumerable()
select r
where r["columnName"] = "the value").ToList()
This syntax is probably a bit off, but it looks something like that.
Edit
Your Model:
Public Class EmployeeModel
Public Property Id
Public Property FirstName
Public Property Last Name
Public Property JobCode
Public Sub EmployeeModel(your params)
//set properties
End Sub
End Class
Your DAL:
Public Shared Class EmployeeDAL
Public Shared Sub SaveEmployee(ByRef model as EmployeeModel)
// call your sp_SaveEmployee stored procedure and set the parameters to the model properties
// #id = EmpoyeeModel.Id
// #JobCode = Employee.JobCode
// ...
End Sub
End Class
I use VB every few months, so there are probably some small syntax errors in there. But that's basically all you need to do. The function to save your data is in the DAL, not in the class itself. If you don't want to use a DAL, you can put the save functionality in your class, though. It'll work the same way, it's just not as clearly separated.
On your Questions.
number 1: You have to connect to database in order to store and retrieve data. There are lots of ways on how to deal with it and one way of it is to use app.config or you may simply create a function that calls the connection every time you need it.
number 2: Since you are dealing with dataset here are some tips you might want to look at DataSet
number 3: You can also try using Data Adapter and Data Table. I am not sure what you meant by your question number 3.
Cheers
I have problem with the way you are using your database and the ram of your computer.
Problem1: since you already have a database for holding the movies information why are you again holding the same information in memory?, creating an extra overhead. if your answer is for performance or i have cheap memory then why don't you use xml or flatfile instead? Database is not needed with this senario.
Problem2: You are like a soldier who dosent know about the weapon he use? right? because you are asking silly questions your first question about opening connection.. the answer is yes you have to open the connection every time save/read the data and close it as soon as possible.
your second question about convinent the answer is no. instead create class with all field as property and some method for initialization,saving,deleting. this way you have to write less code. nad suppose you have a movie names xyz there can be another movie xyz how will you distinguish it? if you have whole information b4 you you can do it via release date ,casts etc, but still it will be hard, so create a primary key for both your table
and finally your 3rd question , it will be easier to use use sql queries than looping thru the dataset(get rid of the dataset as soon as possible)
wish yu good luck on the road to rdbms

Hibernate Entity Manager: Result Set Mapping

I'm new to Hibernate and I am a fan of iBATIS, but my new work environments forces me to use Hibernate. In the current scenario at my workplace, there are many complex select queries that I feel hibernate doesn't handles very well.
So I thought of writing my own native SQL select queries, with lots and lots of joins and conditions. So far so good.
I'm using the EntityManager to fire the queries and return the result set. The sample code will look like this:
String sqlQuery="select COL_1, COL_2 from MY_TABLE_NAME";
Query q=em.createNativeQuery(sqlQuery,);
List resultList=q.getResultList();
Please keep in mind this is just a code sample. I would like to have a way so that the result set as in this example (COL_1 and COL_2) can be mapped to my JAVA Class that has two (or more) fields.
Also note that this JAVA Class can not be an Entity that is linked to a table, So I need a way to define any of my JAVA class as a resultClass, the way we do in iBATIS.
Is there any way to do it? SO that the I just define a mapping somewhere for any JAVA class and the result set from query gets mapped to my JAVA Class automatically
String sqlQuery="select COL_1, COL_2 from MY_TABLE_NAME";
Query q=em.createNativeQuery(sqlQuery,MY_TABLE_NAME.class);
List<MY_TABLE_NAME> resultList=q.getResultList();
look variable in IDE debug mode, you will get what you want.

Is there any overhead with LINQ or the Entity Framework when getting large columns as part of an entity?

Let's say you have a table containing articles and you want want to display a list of them, excluding the actual article text. When you get a list of the article objects using LINQ or the Entity Framework, is there a LOT of overhead associated with getting that text column too? I assume that when you start enumerating the list, the article text will be stored in memory until the objects are disposed of.
So would it make sense to create an intermediary object that doesn't contain the text column? If so, how would you do this? Make a class inside your DAL, allow the ORM to automatically create one by setting up a stored procedure, or some other process?
The overhead isn't huge (just the cost of sending the data over the wire), but if you don't need the data sure, don't return it. I find the easiest way is to use anonymous types:
from a in Context.Articles
select new {Name = a.Name, Author = a.Author};
Since you're not actually materializing any Article instances, the Entity Framework won't need to fill out all the properties of an instance.
If you don't need the data you should definitely create a different type. By convention I typically name this sort of class "nnnInfo" or "nnnListItem". To create ArticleListItem, in L2S, simply drag the table to your DataContext designer a second time. Then rename it from 'Article1' to 'ArticleListItem' and remove the unneeded properties (rt click, delete). In EF, the process would be similar. As Craig notes, you could use anonymous types, but by creating a concrete type, you can reuse throughout your app, expose via services, etc.
A second way to do this would be to create the class manually and write an extension method to return ArticleListItem:
public static IQueryable<ArticleListItem> ToListItems(this IQueryable<Article> articles)
{
return from a in articles select new ArticleListItem{ Title = a.Title, ...}
}
This would allow you to "cast" any queries against Article as ArticleListItem...

Resources