Is it possible to use Linq-to-SQL with nhibernate envers? - c#

Is there a way to use Linq-to-SQL with nhibernate envers to query through revisions without having to use envers audit expressions?
I would like to avoid using something like this, which requires hardcoded string property names:
reader.CreateQuery()
.ForEntitiesAtRevision(1)
.Add(AuditEntity.Property("FirstName").Eq("bob"))
.Results();

No. The only built in query api is the "criteria like" you mention.

Related

Entity framework using statement with Dapper

All of my existing using statements look like the following:
using (var context = new AppContext())
{
}
Now what if I want to use Dapper to pass a sql string directly to the database rather than:
context.Database.SqlQuery(sql);
After looking at the Dapper documenation it looks like it just uses a regular connection string. I am unsure of how to adjust my using statement declaration.
I want to be able to do the following like all of the Dapper examples show:
connection.Query(sql);
I am really hoping dapper will help me with populating custom properties. For example I used a partial class to extend one of my entity framework properties. Currently when I use pass a sql query through linq this property does not get populated even though it is in the Select.
Just use context.Database.Connection.Query<T>() from Dapper since it is just an extension to DbConnection.

Automapper , Linq and Localizaton

Recently I have been playing with AutoMapper as a tool to populate our DTOs.
The cool thing about AutoMapper is its Project().To() that let us map a Queryable so that we can select the fields that we want according to our map.
But here we have another scenario too.We want to be able to translate some of the values of an entity into other representation.
Suppose that we have a string field that its value in DB is 'Apparatment' and we want to translate it to another language while we are selecting our DTOs.
I think that if we want to write this in SQL it will be something like this :
SELECT CASE BuidlingType WHEN 'Appartment' THEN 'apparatment in another langaure' WHEN 'Flat' THEN 'flat in another languate' END AS BuildingType FROM buildings
I know that we can define value resolvers in AutoMapper. The question I would like to ask is ,can we use these resolvers in a Project().To() scenario ? If the answer is yes then how we should use them (to return an expression instead of a value) and if not , is there any other alternative approach to be able to translate a DTO on the fly ?
No you can't use resolvers in LINQ projections.
I guess I'm a little confused - those translations look a little difficult in the SQL you have. Are your translations stored in a database, or do you hard code them in your SQL?
Typically my localized labels are stored either in resource files or specialized tables. If they're in tables, I don't necessarily returned translated data labels with data. I have two queries and the translation query is almost certainly cached.
I would start with "What LINQ do I build to make the correct SQL" and then I can help with "how can I configure AutoMapper to build this LINQ?"

NHibernate generic repository without LINQ extension?

I'm looking for answers from a few days ago with no results.
I'm trying to make an implementation of an IRepository interface for generic repository using NHibernate. Here is the interface:
public interface IRepository<TEntity, TKey> where TEntity : BaseEntity
{
TEntity GetById(TKey id);
void Insert(TEntity entidad);
void Update(TEntity entidad);
void Delete(TEntity entidad);
IQueryable<TEntity > Table { get; };
}
I know that there is an extension for the ISession interface, that brings the use of LINQ in my querys, but also I know that that plugin isn't working at 100% (I tested it but when I try to execute some complicated queryes, it thwows not implemented exception, so I can't use that plugin)
I'm using 100% the QueryOver function from the ISession, so.. Do you know any way to implement the IQueroOver function as IQueryable (without launch a "SELECT * " query)? If not, any others ideas for implement the generic repository pattern without use the LINQ extension?
Thank you very much
There's no such thing
Each person has their own definition of what features a 100% implemented LINQ provider should have.
One might expect a LINQ provider to be able to translate String.Equals(String, String, StringComparison) to a SQL expression that uses the correct collation, but unless the programmers who created the LINQ provider programmed it to do so, it's not going to be able to do it.
There is no end to the things we might want a LINQ provider to be able to do, so every LINQ provider has limitations.
There is no such thing as 100% when it comes to LINQ providers.
It is an unattainable concept.
It is infinity.
Thus, it is important to...
know the limitations of your LINQ provider, and
know how to work around those limitations.
Limitations
With NHibernate, knowing the limitations is a bit harder than it should be, because there is currently no official documentation for the NHibernate LINQ provider.
(NH-2444, patches are welcome!)
However, you can figure some of it out just by knowing that this LINQ provider is built on top of HQL, so any limitations that HQL has, LINQ will have as well.
There is no NHibernate query syntax that directly supports performing arbitrary left outer joins on unrelated columns (besides Native SQL, of course).
Queries in NHibernate are designed so that all of the information to perform a join is already stored in the mappings.
After that, all you have to do is specify the relationship, such as order.Customer, and NHibernate knows which tables and columns to join together. You should be able to do arbitrary cross joins using HQL or LINQ, and then you could add a where clause to make it behave like an inner join, but no left outer join.
Since none of the query syntaxes directly support what you want to do, building a LINQ/QueryOver wrapper (as apposed to the existing LINQ/HQL wrapper, and probably just as complex to implement) will gain you nothing.
You'll have to take the same steps to deal with this query whether you're using LINQ or QueryOver.
Workarounds
Since it is not possible for a LINQ provider to be complete, a well designed LINQ provider must be extensible.
That way, if the LINQ provider doesn't natively support the functionality you need, it doesn't ruin your day.
The NHibernate LINQ provider can be extended.
See Giorgetti Alessandro's blog for more information.
But of course, before we go off writing LINQ provider extensions, we should check to see if there's a simpler way to solve the problem.
A couple of possibilities come to mind:
The easiest way to handle this is to simply add the relationship to your NHibernate mappings, enabling you to leverage it in NHibernate queries (LINQ, or whatever).
If the two columns are of incompatible data types, or require some kind of manipulation before you can perform the join, consider fixing the data and the schema in order to enable a smoother mapping.
Another option is to get creative with subqueries or use multiple queries to emulate what your desired join would do. For example, see one of my other answers:
... this LEFT OUTER JOIN can be simulated by combining the results of two separate queries - one to get the orders...
var orders = session.Query<OrderHeader>()
.Fetch(x => x.CreatedBy);
... and another to get the people that have no orders:
var peopleWithNoOrders = session.Query<Person>()
.Where(p => !session.Query<OrderHeader>().Any(o => o.CreatedBy == p));
... because a left outer join is equivalent to an inner join plus additional results for non-matches. I don't know the details of the join you're trying to perform, but hopefully this will give you enough ideas to get started.

Using DateTime.Add(TimeSpan) with LINQ

I have to run a query like the one bellow. It is actually more complex, but here is the part that matters:
var results =
from b in _context.Bookings
where b.ScheduleDate.Add(b.StartTime) >= DateTime.UtcNow
select b;
But it gives the following error:
LINQ to Entities does not recognize the method 'System.DateTime.Add
method(System.TimeSpan)', and this method cannot be translated into a
store expression.
How can I work around this?
Thanks in advance.
Try using the SqlFunctions.DateAdd method in the System.Data.Objects.SqlClient namespace. Documentation here. That will convert into the SQL method DateAdd, documented here. You might also be interested in using DateDiff instead, documented here.
In general, look at SqlFunctions for "common language runtime (CLR) methods that call functions in the database in LINQ to Entities queries." LINQ to Entities cannot convert any method call into SQL, but the functions in that class will work.
Your other option is to execute the LINQ to Entities query (using ToList or something similar) and then perform the logic in memory.
SqlFunctions only works with Microsoft Sql Server.
In pure EF you can write:
DbFunctions.AddMilliseconds(x.Date, DbFunctions.DiffMilliseconds(TimeSpan.Zero, x.Time))
This works on all database adapters

Why won't entity framework allow me to do a .FindBy....()

I create a EDM using my database and saw that while it was able to make relations like
Customers.First().Orders
there is nothing like
Customer.First().Orders.FindOrderByOrderID()
Customer.First().Orders.FindOrderByOrderName()
etc.
Maybe I was expecting it to be like that and that's how it doesnt work
and I will probably just have to LINQ to entities and create mangers that handle business logic in them.
or does LINQ to SQL do this?
You can use LINQ with the Orders property, like this:
var order = Customer.First().Orders.FirstOrDefault(o => o.OrderId == someId);
This will return null if there was no matching Order.
With LINQ to Entities you can do this. Such as the example SLaks posted above.
If you're feeling adventurous, it is possible to write a function to do this. Since Entity Framework knows which column is the primary key it is possible to write a function like GetEntityByPrimaryKey.
CodeProject has an article regarding the repository pattern and if you search for "SelectByKey" you'll see their implementation of that. I use something similar and find it very helpful.
The idea is that you can use LINQ to write more flexible queries. Note, however, that you could probably so something like FindOrderByOrderName in .NET 4.0 by creating your own dynamic type (not trivial), that responded to calls following this pattern by building a LINQ query automatically. You'd lose intellisense, of course, and I doubt it would be worth it, but it could be done.

Categories

Resources