Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a complex type from a stored procedure that uses exec()?

I want to create a complex type to use within an entity manager from a query constructed dynamically and executed with exec(). Is it possible?; since I'm writing a filter, what would you do instead if it is not possible?

Also, I'm evaluating using linq, but the filter needs many tables and their registers, therefore efficiency is a concern.

Thanks...

like image 227
JPCF Avatar asked Sep 16 '10 15:09

JPCF


People also ask

How do I add a complex type to Entity Framework?

On the designer surface, select one or more properties (excluding navigation properties) of an entity, then right-click and select Refactor -> Move to New Complex Type. A new complex type with the selected properties is added to the Model Browser. The complex type is given a default name.

Can we use multiple SELECT statements in a stored procedure SQL Server?

Each procedure has one or more statements. In our case, these are SQL statements. So, you can write a procedure that will – insert new data, update or delete existing, retrieve data using the SELECT statement. And even better, you can combine more (different statements) in the stored procedures.

Which is faster LINQ or stored procedure?

Stored procedures are faster as compared to LINQ query since they have a predictable execution plan and can take the full advantage of SQL features. Hence, when a stored procedure is being executed next time, the database used the cached execution plan to execute that stored procedure.


2 Answers

Yes, you can use Entity Framework 4 and LINQ on top, it generates the parametrized query and executes it, that's the option.

Another option is (and I did several times) to create a base class/interface, let's say:

public interface IExecutable
{
    void Execute(IConnection connection);
}
public interface IExecutable<TResult> : IExecutable
{
    TResult Result { get; }
}

public abstract ActionBase<TResult> : IExecutable<TResult>
{
    protected void AddParameter(....);

    protected IDataReader ExecuteAsReader(string query) {
        //create a DB Command, open transaction if needed, execute query, return a reader.
    }

    protected object ExecuteAsScalar(string query) {
        //....
    }

    //the concrete implementation
    protected abstract TResult ExecuteInternal();

    IExecutable.Execute(IConnection connection) {
        //keep the connection
        this.Result = ExecuteInternal();
    }

    //another common logic: 

}

Then you can create your concrete actions:

public sealed class GetUsersAction : ActionBase<<IList<User>>
{
    //just a constructor, you provide it with all the information it neads
    //to be able to generate a correct SQL for this specific situation
    public GetUsersAction(int departmentId) {
        AddParameter("@depId", departmentId);
    }

    protected override IList<User> ExecuteInternal() {
        var command = GenerateYourSqlCommand();

        using(var reader = ExecuteAsReader(command)) {
            while(reader.Read) {
                //create your users from reader
            }
        }
        //return users you have created
    }
}

Very easy to create concrete actions!

Then, to make it even easier, create an ExecutionManager whose concern is how to get the connection and execute the action:

public sealed ExecutionManager() {

    TResult Execute<TResult>(IExecutable<TResult> action) {
        var connection = OhOnlyIKnowHowTOGetTheConnectionAnfHereItIs();
        action.Execute(connection);
        return action.Result;
    }
}

Now just use it:

var getUsersAction = new GetUsersAction(salesDepartmentId);

//it is not necessary to be a singletone, up to you
var users = ExecutionManager.Instance.Execute(getUsersAction);

//OR, if you think it is not up to ExecutionManager to know about the results:
ExecutionManager.Instance.Execute(getUsersAction);
var users = getUsersAction.Result

Using this simple technique it is really easy to move all the connection/command/execution logic away from the concrete actions into the base class, and the concrete actions' concerns are just generating SQLs and converting database output into some meaningful results.

Good luck :)

like image 179
Alexey Raga Avatar answered Sep 22 '22 01:09

Alexey Raga


If you decide to go the Linq route and are looking for a good way to do filtering. LinqKit is a great library for building ad-hoc predicates. The problem with the built-in linq library is that you can only ad-hoc combine AND statements, you can not ad-hoc combine OR statements. Linqkit makes that a breeze to accomplish.

like image 25
Markis Avatar answered Sep 21 '22 01:09

Markis