Running sql in entity framework? - entity-framework

Is there any way to run a sql statement straight from the entity framework generated calls? Or will I have to create a procedure then call that via the entity framework?

Was Googling around for this myself the other day, this is the example I found hope it helps
static void ExecuteSql(ObjectContext c, string sql)
{
var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection;
DbConnection conn = entityConnection.StoreConnection;
ConnectionState initialState = conn.State;
try
{
if (initialState != ConnectionState.Open)
conn.Open();
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
finally
{
if (initialState != ConnectionState.Open)
conn.Close();
}
}

In EF 4.0 this is pretty easy because there are new methods on the ObjectContext that allow you to execute store commands (i.e. SQL) directly:
See this: ExecuteStoreCommand
If you are still using EF 3.5 SP1 you can still execute a query directly against the database if you really want to like this:
var econn = ctx.Connection as EntityConnection;
var dbconn = econn.StoreConnection;
at this point you have access to a connection (dbconn) to the underlying database, so you can use normal ADO.NET code to execute queries etc.
Hope this helps
Alex

ExecuteStoreQuery<> and ExecuteStoreCommand is what you want:
using (NorthWindEntities ctx = new NorthWindEntities())
{
ctx.ExecuteStoreQuery<>()
ctx.ExecuteStoreCommand();
}

#Alex James, out of curiosity, would this be efficient to run a full text sql bit of code, as in there should be no performance overhead right? To say, running the same full text sql code straight as a query in sql management studio.

Related

How to log SQL Queries

I want to log SQL Queries, to examine what exactly is my LINQ queries doing to understand how can I improve it.
But I can't find how to logging it.
I did it like this:
Change DbContextConfigurer in EntityFramework project
as:
public static void Configure(DbContextOptionsBuilder<TestDbContext> builder, string connectionString, **ILoggerFactory loggerFactory = null**)
{
**builder.UseLoggerFactory(loggerFactory);**
builder.UseSqlServer(connectionString);
}
Then add in file MyProjectEntityFrameworkCoreModule.cs into PreInitiallize section
public override void PreInitialize()
{
if (!SkipDbContextRegistration)
{
Configuration.Modules.AbpEfCore().AddDbContext<TestDbContext>(options =>
{
if (options.ExistingConnection != null)
{
TestDbContextConfigurer.Configure(options.DbContextOptions, options.ExistingConnection);
}
else
{
**var loggerFactory = IocManager.Resolve<ILoggerFactory>();**
TestDbContextConfigurer.Configure(options.DbContextOptions, options.ConnectionString,**loggerFactory**);
}
});
}
//Uncomment below line to write change logs for the entities below:
//Configuration.EntityHistory.Selectors.Add("TestEntities", typeof(OrganizationUnit), typeof(Role), typeof(Tenant));
}
If you are using MSSQL with EF and intend to troubleshoot how LINQ is being translated into SQL statement. You can try SQL Profiler that comes together with MSSQL Database Engine
With SQL Profiler, you are able to record and trace tsql event in it. With proper isolation of the LINQ call in your application, you can trace the SQL statement received by the Database engine.
https://learn.microsoft.com/en-us/sql/relational-databases/event-classes/tsql-event-category?view=sql-server-2017

.NET: NpgsqlCommand to IQueryable

Is there a way to create an IQueryable from an NpgsqlCommand?
Something like this:
using (var connection = new NpgsqlConnection(_connectionString))
{
connection.Open();
using (var cmd = new NpgsqlCommand("SELECT o.Id, o.Name FROM schema.blogs", connection))
var blogsQueryable = cmd.Execute<IQueryable<BlogViewModel>>;
}
Npgsql on its own is just an ADO.NET provider, and as such does not map rows to your own objects.
You should take a look at Entity Framework Core for a full O/RM, or at Dapper for a lighter solution.

Entity Framework Db.SaveChanges() not working?

Can u tell me what is the problem?
If you are using two different instances of the DbContext (the db variable as you named it) then nothing will be saved when you call SaveChanges on a context different than the one where your entities are tracked. You need to use the Attach method first.
db.customer_images.Attach(item);
db.SaveChanges();
However I think in your case you can avoid the attach step if you refactor a bit you code and don't use the DbContext from the entity itself.
Before going through my answer, you must check, if you are attaching the item as shown in excepted answer or check this code:.
if (dbStudentDetails != null && dbStudentDetails.Id != 0)
{
// update scenario
item.Id = dbStudentDetails.Id;
_context.Entry(dbStudentDetails).CurrentValues.SetValues(item);
_context.Entry(dbStudentDetails).State = EntityState.Modified;
}
else
{
// create scenario
_context.StudentDetails.Add(item);
}
await _context.SaveChangesAsync();
If above solution doesn't work, then check the below answer.
Saw a very wired issue, and thought to must answer this. as this can
be a major issue if you have lots of constraints and indexes in your
SQL.
db.SaveChanges() wasn't throwing any error, but not working (I have tried Exception or SqlException). This was not working because the Unique constraint was not defined properly while creating the Entity Models.
How you can Identified the issue:
I connected my SQL Server and opened the SQL Profiler.
Just before the db.SaveChanges(), I cleared all my profiler logs and ran the db.SaveChanges(). It logged the statement. I copied the script from the profiler and ran the script in SQL Server.
And bingo, I can see the actual error, which is being thrown at SQL Server side.
(images: have some hints, how you can get the execute statement from Profiler and run on sql server)
What you can do For Entity Framework Core:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Students>().HasIndex(p => new { p.RollNumber, p.PhoneNumber }).IsUnique(true).IsClustered(false).HasDatabaseName("IX_Students_Numbers");
}
What you can do For Entity Framework 6 and below:
using System.Data.Entity.ModelConfiguration;
internal partial class StudentsConfiguration : EntityTypeConfiguration<Students>
{
public StudentsConfiguration()
{
HasIndex(p => new { p.RollNumber, p.PhoneNumber }).IsUnique(true).IsClustered(false).HasName("IX_Students_Numbers");
}
}
Try to query your entity by Id, eg:
entity = this.repo.GetById(item.id);
entity.is_front = false;
if (dbSaveChanges() > 0)
{
....
}

MiniProfiler setup - A null was returned after calling the 'get_ProviderFactory' method

After hours of struggling with MiniProfiler to make it profile the Database queries, I have no luck and I'm getting the error:
A null was returned after calling the 'get_ProviderFactory' method on
a store provider instance of type
'StackExchange.Profiling.Data.ProfiledDbConnection'. The store
provider might not be functioning correctly.
I got through many SO posts but nothing has worked so far, like this post which is about the same error but with different configuration and well there's not an answer. Now I know that ProfiledDbConnection is not overriding DbProviderFactory and it's parent class DbConnection returns null in it's implementation of DbProviderFactory so the error is expectable but it should work somehow. There is a MiniProfilerEF.Initialize() but it seams to be usable for CodeFirst only and I'm using DatabaseFirst approach.
I have installed MiniProfiler, MiniProfiler.EF, MiniProfilerMVC3 nuget packages. And here is my code:
string connectionString = ConfigurationManager.ConnectionStrings["SqlConnection"].ConnectionString;
var sqlConnection = new SqlConnection(connectionString);
var profiled = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var db = new DbContext(profiled, true);
db.Set<Customer>().ToList();
And I'm using asp.net mvc4, EF5, DatabseFirst, MiniProfiler 2.1.0.0, Sql Server
Any Idea?
So, coming from your comment on Setup of mvc-mini-profiler for EF-db- first, have you tried removing the Mini Profiler-specific wrapper?
var profiled = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var db = new DbContext(profiled, true);
db.Set<Customer>().ToList();
Instead, just adding
protected void Application_Start()
{
// any other code
MiniProfilerEF.Initialize();
}
and then doing standard db access?
using (var db = new WordsEntities()) {
var posts = db.Customer.Take(4);
// more code
}

Calling stored procedure from Entity Framework 3.5

I"m using VS 2010 & EF 3.5. I've imported a stored procedure which returns a list of guids using the Function Import feature. How do I invoke it in my code? After instantiating the dbcontext, intellisense doesn't display the procedure I've imported. I know it's pretty easy in EF 4.0 but I'm stuck with EF 3.5 for this project. Any ideas on how get around this other than doing it the old-fashioned way?
I don't think EF versions prior to 4 can use imported stored procedures that don't return entities. That is, your stored procedure must return a complete entity object in order for EF to use it. Since your procedure only returns a list of GUIDs, EF doesn't know how to use it.
You can put this in your partial data-context class to call the procedure:
public IEnumerable<Guid> GetMyGUIDs()
{
if (this.Connection.State != System.Data.ConnectionState.Open)
this.Connection.Open();
var command = new System.Data.EntityClient.EntityCommand
{
CommandType = System.Data.CommandType.StoredProcedure,
CommandText = #"YourContext.YourProcedureName",
Connection = (System.Data.EntityClient.EntityConnection)this.Connection
};
var list = new List<Guid>();
using (var reader = command.ExecuteReader())
{
// get GUID values from the reader here,
// and put them in the list
reader.Close();
}
return list;
}