2

I am trying to create a dynamic way to generate report using ASP.NET MVC 5 and Entity framework in C#.

I am going to give the user a list of the available fields, ability to add filter, and ability to create a cross join from one object to another. The user decides which column and filter he/she wants to use for their custom report. Finally, I create the correct SQL query, pull the data and display it. I will need to do two main things here

  1. Create queries on the fly
  2. Build a model of the requested report on the fly

For example, I have the following two simple models

public class Customer 
{
    [Key]
    public int Id { get; set ; }

    public string FirstName { get; set ; }

    public string LastName { get; set ; }

    public string Phone { get; set ; }

}

public class Transaction 
{
    [Key]
    public int Id { get; set ; }

    [ForeignKey("Customer")]
    public int CutomerId { get; set ; }

    public decimal Amount { get; set ; }

    public DateTime CreatedAt { get; set ; }

    public Customer Customer { get; set; }

}

Assuming, the user wants a report that shows the customer first name, last name, phone, the sum of all their transaction and count them. The following query will give me exactly the report requirements.

SELECT c.FirstName, c.LastName, c.Phone, SUM(t.Amount) AS Amount,   COUNT(*) AS total
FROM Customers AS c
INNER JOIN Transactions AS t ON t.CustomerId = c.Id
WHERE c.CreatedAt BETWEEN '2015-01-01' AND '2016-01-01'
GROUP BY c.FirstName, c.LastName, c.Phone
ORDER BY c.FirstName, c.LastName

But since this is going to be a user friendly tool I will need to be able to use either use Fluent or LINQ to generate the queries on the fly to get the data.

To convert my query to LINQ syntax, I will have to do something like this

var data = from customer in customers
    join transaction in transactions on transaction.CustomerId = customer.Id
    group customers by new { customer.FirstName, customer.LastName, customer.Phone } into g
    order by customer.FirstName, customer.LastName
    select new {
        FirstName = g.FirstName, 
        LastName = g.LastName, 
        Phone = g.Phone,
        Amount = g.Sum(s => s.Amount)
        Total = g.Count()
    }

Is there a way to know the relation between models using Entity framework and the keys so I can use to join the tables? Also, is there a way to get the available attributes for each object from Entity so I can list the fields for the user?

Also, how can I create a model on the fly where I can pass it to a view for display?

Jaylen
  • 39,043
  • 40
  • 128
  • 221
  • Why not put this query into a `Stored Procedure` and call that sp from your application, will benefit from the `cached execution plans`, EF is a cool tool for .net developers to map db objects in their application but if you can write decent sql (as you have) you should put them in sps and call the SP at runtime rather than using Linq. – M.Ali Jun 26 '16 at 22:18
  • I need to be able to build the query on the fly based on the user request. I am not sure how Stored procedures will help me here. each user can have different requirements. and the models will be more advanced that the code I listed in my question – Jaylen Jun 26 '16 at 22:23
  • This is where the Dynamic SQL comes into play, when using Dynamic sql use `sp_executesql` inside your procedure and this will `cache parameterized execution plans` , again queries on the fly is not an answer but yes an SP is. – M.Ali Jun 26 '16 at 22:28
  • So I will still need to create the query on the fly and then send it to the SP to execute it. correct? – Jaylen Jun 26 '16 at 22:36
  • No you only pass parameters to the Stored procedure (google Optional Parameters to SQL Server Stored Procedure) , based on the parameters you pass to the SP the query is dynamically build inside the sp and then use system stored procedure `sp_executesql` to execute that query, sp_executesql has the capability of caching parameterised execution plans, which means one SP can have multiple execution plans depending on the combinations of parameters you pass. – M.Ali Jun 26 '16 at 22:41
  • I guess SP would work if I am using the same tables over and over. Remember that the user will have the ability to add cross join to get columns from other tables. – Jaylen Jun 26 '16 at 22:50
  • You might be able to use Reflection to get the properties for a table class. For the key columns, you could perhaps use reflection to search for the Key attribute. http://stackoverflow.com/questions/2281972/how-to-get-a-list-of-properties-with-a-given-attribute – failedprogramming Jun 26 '16 at 23:03

0 Answers0