यह समाधान @ पायस से समाधान पर भारी पड़ता है। मैं SQL इंजेक्शन को कम करने में मदद करने के लिए क्वेरी मापदंडों का समर्थन करने के लिए विकल्प जोड़ना चाहता था और मैं इसे एंटिटी फ्रेमवर्क कोर के लिए DbContext DatabaseFacade का एक विस्तार बंद करना चाहता था ताकि इसे थोड़ा और एकीकृत किया जा सके।
पहले एक्सटेंशन के साथ एक नया वर्ग बनाएं:
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
namespace EF.Extend
{
public static class ExecuteSqlExt
{
/// <summary>
/// Execute raw SQL query with query parameters
/// </summary>
/// <typeparam name="T">the return type</typeparam>
/// <param name="db">the database context database, usually _context.Database</param>
/// <param name="query">the query string</param>
/// <param name="map">the map to map the result to the object of type T</param>
/// <param name="queryParameters">the collection of query parameters, if any</param>
/// <returns></returns>
public static List<T> ExecuteSqlRawExt<T, P>(this DatabaseFacade db, string query, Func<DbDataReader, T> map, IEnumerable<P> queryParameters = null)
{
using (var command = db.GetDbConnection().CreateCommand())
{
if((queryParameters?.Any() ?? false))
command.Parameters.AddRange(queryParameters.ToArray());
command.CommandText = query;
command.CommandType = CommandType.Text;
db.OpenConnection();
using (var result = command.ExecuteReader())
{
var entities = new List<T>();
while (result.Read())
{
entities.Add(map(result));
}
return entities;
}
}
}
}
}
उपरोक्त में ध्यान दें कि "T" रिटर्न के लिए प्रकार है और "P" आपके क्वेरी मापदंडों का प्रकार है, जो इस आधार पर भिन्न होगा कि क्या आप MySql, Sql, इत्यादि का उपयोग कर रहे हैं।
आगे हम एक उदाहरण दिखाएंगे। मैं MySql EF Core क्षमता का उपयोग कर रहा हूं, इसलिए हम देखेंगे कि हम इस अधिक विशिष्ट MySql कार्यान्वयन के साथ जेनेरिक एक्सटेंशन का उपयोग कैसे कर सकते हैं:
//add your using statement for the extension at the top of your Controller
//with all your other using statements
using EF.Extend;
//then your your Controller looks something like this
namespace Car.Api.Controllers
{
//Define a quick Car class for the custom return type
//you would want to put this in it's own class file probably
public class Car
{
public string Make { get; set; }
public string Model { get; set; }
public string DisplayTitle { get; set; }
}
[ApiController]
public class CarController : ControllerBase
{
private readonly ILogger<CarController> _logger;
//this would be your Entity Framework Core context
private readonly CarContext _context;
public CarController(ILogger<CarController> logger, CarContext context)
{
_logger = logger;
_context = context;
}
//... more stuff here ...
/// <summary>
/// Get car example
/// </summary>
[HttpGet]
public IEnumerable<Car> Get()
{
//instantiate three query parameters to pass with the query
//note the MySqlParameter type is because I'm using MySql
MySqlParameter p1 = new MySqlParameter
{
ParameterName = "id1",
Value = "25"
};
MySqlParameter p2 = new MySqlParameter
{
ParameterName = "id2",
Value = "26"
};
MySqlParameter p3 = new MySqlParameter
{
ParameterName = "id3",
Value = "27"
};
//add the 3 query parameters to an IEnumerable compatible list object
List<MySqlParameter> queryParameters = new List<MySqlParameter>() { p1, p2, p3 };
//note the extension is now easily accessed off the _context.Database object
//also note for ExecuteSqlRawExt<Car, MySqlParameter>
//Car is my return type "T"
//MySqlParameter is the specific DbParameter type MySqlParameter type "P"
List<Car> result = _context.Database.ExecuteSqlRawExt<Car, MySqlParameter>(
"SELECT Car.Make, Car.Model, CONCAT_WS('', Car.Make, ' ', Car.Model) As DisplayTitle FROM Car WHERE Car.Id IN(@id1, @id2, @id3)",
x => new Car { Make = (string)x[0], Model = (string)x[1], DisplayTitle = (string)x[2] },
queryParameters);
return result;
}
}
}
क्वेरी पंक्तियों को लौटाएगी जैसे:
"Ford", "Explorer", "Ford Explorer"
"Tesla", "Model X", "Tesla Model X"।
प्रदर्शन शीर्षक को डेटाबेस कॉलम के रूप में परिभाषित नहीं किया गया है, इसलिए यह डिफ़ॉल्ट रूप से EF कार मॉडल का हिस्सा नहीं होगा। मैं इस दृष्टिकोण को कई संभावित समाधानों में से एक के रूप में पसंद करता हूं। इस पृष्ठ के अन्य उत्तर इस मुद्दे को संबोधित करने के अन्य तरीकों को संदर्भित करते हैं [नोटमैपेड] डेकोरेटर के साथ, जो आपके उपयोग के मामले के आधार पर अधिक उपयुक्त दृष्टिकोण हो सकता है।
ध्यान दें कि इस उदाहरण में कोड स्पष्ट रूप से अधिक क्रियात्मक है जितना कि इसकी आवश्यकता है, लेकिन मुझे लगा कि इसने उदाहरण को स्पष्ट कर दिया है।