Bu çözüm, büyük ölçüde @pius'un çözümüne dayanıyor. SQL enjeksiyonunu azaltmaya yardımcı olmak için sorgu parametrelerini destekleme seçeneğini eklemek istedim ve onu biraz daha entegre hale getirmek için Entity Framework Core için DbContext DatabaseFacade dışında bir uzantı yapmak istedim.
Önce şu uzantıyla yeni bir sınıf oluşturun:
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
{
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;
}
}
}
}
}
Yukarıda "T" nin dönüş türü ve "P" nin MySql, Sql, vb. Kullanmanıza bağlı olarak değişecek olan sorgu parametrelerinizin türü olduğunu unutmayın.
Sonra bir örnek göstereceğiz. MySql EF Core özelliğini kullanıyorum, bu nedenle yukarıdaki genel uzantıyı bu daha spesifik MySql uygulamasıyla nasıl kullanabileceğimizi göreceğiz:
using EF.Extend;
namespace Car.Api.Controllers
{
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;
private readonly CarContext _context;
public CarController(ILogger<CarController> logger, CarContext context)
{
_logger = logger;
_context = context;
}
[HttpGet]
public IEnumerable<Car> Get()
{
MySqlParameter p1 = new MySqlParameter
{
ParameterName = "id1",
Value = "25"
};
MySqlParameter p2 = new MySqlParameter
{
ParameterName = "id2",
Value = "26"
};
MySqlParameter p3 = new MySqlParameter
{
ParameterName = "id3",
Value = "27"
};
List<MySqlParameter> queryParameters = new List<MySqlParameter>() { p1, p2, p3 };
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;
}
}
}
Sorgu,
"Ford", "Explorer", "Ford Explorer"
"Tesla", "Model X", "Tesla Model X" gibi satırlar döndürür
Görüntü başlığı bir veritabanı sütunu olarak tanımlanmaz, bu nedenle varsayılan olarak EF Araba modelinin bir parçası olmaz. Bu yaklaşımı birçok olası çözümden biri olarak seviyorum. Bu sayfadaki diğer yanıtlar, kullanım durumunuza bağlı olarak daha uygun bir yaklaşım olabilecek [Eşlenmemiş] dekoratörle bu sorunu ele almanın diğer yollarına atıfta bulunmaktadır.
Bu örnekteki kodun olması gerekenden açıkça daha ayrıntılı olduğunu unutmayın, ancak örneği daha açık hale getirdiğini düşündüm.