question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to execute a sql string in the application layer

See original GitHub issue

I have a very complex business logic,it’s sql string is

SELECT * FROM 
(SELECT OperatorID,Name,YEAR(OrderDate) AS ye,SUM(PayFee) AS scanCode FROM dbo.Operators JOIN   dbo.Orders ON   dbo.Operators.Id=dbo.Orders.OperatorID GROUP BY OperatorID,name,YEAR(OrderDate)
) AS a
JOIN (SELECT OperatorID,SUM(TheDayMoney)AS coinsCast,Year FROM dbo.DeviceCoinsRecords GROUP BY OperatorID,Year
)AS b ON a.OperatorID=b.OperatorID AND a.ye=b.Year WHERE b.Year=YEAR(GETDATE())

How can I do this?

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:23 (12 by maintainers)

github_iconTop GitHub Comments

6reactions
hikalkancommented, May 11, 2016

Hi,

You don’t have to use repositories. Repository is not a good point for such a generic code. Define an interface like this, in your .Core module:

namespace Acme.PhoneBook.Data
{
    public interface ISqlExecuter
    {
        int Execute(string sql, params object[] parameters);
    }
}

Then implement it in your .EntityFramework module:

using Abp.Dependency;
using Abp.EntityFramework;
using Acme.PhoneBook.Data;

namespace Acme.PhoneBook.EntityFramework
{
    public class SqlExecuter : ISqlExecuter, ITransientDependency
    {
        private readonly IDbContextProvider<PhoneBookDbContext> _dbContextProvider;

        public SqlExecuter(IDbContextProvider<PhoneBookDbContext> dbContextProvider)
        {
            _dbContextProvider = dbContextProvider;
        }

        public int Execute(string sql, params object[] parameters)
        {
            return _dbContextProvider.GetDbContext().Database.ExecuteSqlCommand(sql, parameters);
        }
    }
}

Then you can inject ISqlExecuter anywhere you need. And you can use it like that:

public void ActivateAllUsers()
{
    _sqlExecuter.Execute("UPDATE AbpUsers SET IsActive = 1 WHERE TenantId = {0}", AbpSession.TenantId);
}

For the second question, if you use EF’s class, you need to reference to EF, no way. Why don’t you return list of entities if you need to run sql and get a list of entities.

4reactions
mikemey01commented, Oct 13, 2017

@acjh @hikalkan thank you both for the help, I was able to get typed stored proc calls working. Here’s the code:

Interface (in domain project):

public interface IPMStoredProcedureRepository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity: class, IEntity<TPrimaryKey>
{
	List<TEntity> ExecuteSP(string query, params object[] parameters);
}

public interface IPMStoredProcedureRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity<int>
{
	List<TEntity> ExecuteSP(string query, params object[] parameters);
}

Implementation (in EntityFramework project):

public class PMStoredProcedureRepository<TEntity> : MyRepositoryBase<TEntity, int>, IPMStoredProcedureRepository<TEntity> where TEntity : class, IEntity<int>
{
	public PMStoredProcedureRepository(IDbContextProvider<MyDbContext> dbContextProvider) : base(dbContextProvider)
	{
	}

	public List<TEntity> ExecuteSP(string query, params object[] parameters)
	{
		var type = Context.Set<TEntity>().FromSql(query, parameters).AsNoTracking().ToList<TEntity>();
		return type;
	}
}

Then you can inject the repository like any other in the application service layer, providing the type that the Stored Proc will return:

private readonly IPMStoredProcedureRepository<PMTestType> _storedProcRepository;
public AppService(IPMStoredProcedureRepository<PMTestType> storedProcRepository)
{
    _storedProcRepository = storedProcRepository;
}

Then to call the stored proc from the app service, you have to wrap it in a unit of work transaction, otherwise the datareader is not freed correctly:

public List<PMTestType> GetTestSP()
{
	using (var uow = UnitOfWorkManager.Begin())
	{
		var ret = _storedProcRepository.ExecuteSP("pme_TestProcedure @inputString", new SqlParameter("@inputString", "abcde"));
		uow.Complete();
		return ret;
	}
}

Hopefully that helps for anyone else that comes across this issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

sp_executesql (Transact-SQL) - SQL Server
With EXECUTE, each INSERT string is unique because the parameter values are different. Although both methods generate the same number of batches ...
Read more >
Execute Dynamic SQL commands in SQL Server
SQL Server offers a few ways of running a dynamically built SQL statement. Here are a few options: Writing a SELECT statement or...
Read more >
Dynamic SQL in SQL Server
In this article, we will review how to construct and execute dynamic SQL statements in SQL Server with different examples.
Read more >
How to execute an .SQL script file using c# - ...
Put the command to execute the sql script into a batch file then run the below code string batchFileName = @"c:\batosql.bat"; ...
Read more >
SQL Layer
The SQL layer of CockroachDB's architecture exposes its SQL API to developers and converts SQL statements into key-value operations.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found