Сирий запит SQL без DbSet - Entity Framework Core


107

Після видалення ядра Entity Framework dbData.Database.SqlQuery<SomeModel>я не можу знайти рішення для створення необробленого SQL-запиту для мого повнотекстового пошукового запиту, який поверне дані таблиць, а також ранг.

Єдиний метод, який я бачив для побудови необробленого SQL-запиту в Entity Framework Core - це той, dbData.Product.FromSql("SQL SCRIPT");який не є корисним, оскільки у мене немає DbSet, який би відображав рейтинг, який я повертаю у запиті.

Будь-які ідеї ???


15
Я сильно пропущу SqlQuery <T> і не хочу призначати власні класи на мій DbContext, коли мені дійсно потрібен простий DTO для конкретного випадку використання. Я створив голос користувача для запиту додавання цієї функції назад в EF Ядро , що будь-яка людина може голосувати, якщо вони хотіли б цю функцію назад: data.uservoice.com/forums / ...
Matt Sanders

1
За даними github.com/aspnet/EntityFramework/isissue/1862 , це орієнтоване на ядро ​​EF 1.2 та / або 1.1.0-попередній перегляд1
Dan Field

2
Спираючись на те, що щойно сказав @Devon, я витратив занадто довго, просто з'ясувавши, що це методи розширення в Microsoft.EntityFrameworkCore.SqlServer. Вам потрібно буде додати це до свого проекту, перш ніж отримати ці методи розширення.
Даніель

3
Зітхання це здається якимось - то рішення архітектури астронавта: «люди не повинні хотіти цього». Я думаю, я повинен встановити Dapper саме для цього випадку. Дратівливий.
Дірк Бур

1
@MattSanders - Ви, мабуть, посилання на користувальницьку службу, здається, тим часом мертве. Ви знаєте, куди це пішло?
Дірк Бур

Відповіді:


126

Це залежить, якщо ви використовуєте версії EF Core 2.1 або EF Core 3 та новіших версій .

Якщо ви використовуєте EF Core 2.1

Якщо ви використовуєте EF Core 2.1 Release Candidate 1, доступний з 7 травня 2018 року, ви можете скористатися запропонованою новою функцією типу запиту.

Що таке тип запиту ?

На додаток до типів сутності, модель EF Core може містити типи запитів, які можна використовувати для виконання запитів до бази даних щодо даних, які не зіставляються з типами сутності.

Коли використовувати тип запиту?

Служить типом повернення для спеціальних запитів FromSql ().

Картографування до переглядів бази даних.

Картографування до таблиць, для яких не визначено первинний ключ.

Зіставлення запитів, визначених у моделі.

Таким чином, вам більше не потрібно робити усі хаки чи обхідні шляхи, запропоновані як відповіді на ваше запитання. Просто виконайте такі дії:

Спочатку ви визначили нову властивість типу, DbQuery<T>де Tє тип класу, який буде нести значення стовпців вашого запиту SQL. Отже, у DbContextвас буде таке:

public DbQuery<SomeModel> SomeModels { get; set; }

По-друге, використовуйте FromSqlметод, як ви робите з DbSet<T>:

var result = context.SomeModels.FromSql("SQL_SCRIPT").ToList();
var result = await context.SomeModels.FromSql("SQL_SCRIPT").ToListAsync();

Також зауважте, що DdContexts є частковими класами , тому ви можете створити один або декілька окремих файлів, щоб упорядкувати визначення "необробленого SQL DbQuery" якнайкраще вам підходить.


Якщо ви використовуєте EF Core 3.0 та новіші версії

Тип запиту тепер відомий як тип ключової сутності . Як зазначено вище, типи запитів були введені в EF Core 2.1. Якщо ви використовуєте EF Core 3.0 або новішу версію, тепер вам слід подумати про використання безключових типів tntity, оскільки типи запитів тепер позначені як застарілі.

Ця функція була додана в EF Core 2.1 під назвою типів запитів. У EF Core 3.0 концепція була перейменована на безлікарські типи об'єктів. [Keyless] Анотація даних стала доступною в EFCore 5.0.

У нас все ще є ті ж самі сценарії, що і для типів запитів, коли використовувати тип ключових елементів без ключа.

Таким чином , щоб використовувати його необхідно спочатку виділити свій клас SomeModelз [Keyless]анотацією даних або через швидку конфігурацію з .HasNoKey()викликом методу , як показано нижче:

public DbSet<SomeModel> SomeModels { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SomeModel>().HasNoKey();
}

Після цієї конфігурації ви можете скористатися одним із пояснених тут методів для виконання свого SQL-запиту. Наприклад, ви можете використовувати цей:

var result = context.SomeModels.FromSqlRaw("SQL SCRIPT").ToList();

18
Ця відповідь повинна бути найкращим рішенням при використанні EF Core 2.1 і вище. 👍
Уілл Хуанг

2
@CodeNotFound Що робити, якщо мені не потрібен результат або якщо це примітивний тип (наприклад bit)?
Shimmy Weitzhandler

5
За допомогою CodeFirst це автоматично створює таблицю з усіма цими властивостями, додавання [NotMapped]до SomeModelsкласу не працює для мене. Я щось пропустив?
Жан-Поль

7
EF Core 3.0 припиняє свою діяльність DbQueryна користь простого використання DbSetз безключовими типами об'єктів .
NetMage

3
Тільки FYI, через деяку помилку в EF core 3.0, перенесення коду все одно намагатиметься створити таблицю навіть для сутностей, позначених HasNoKey (). Отже, вам потрібно також додати .ToView (null). Наприклад modelBuilder.Entity<MyData>().HasNoKey().ToView(null);@ Jean-Paul Я думаю, це вирішує вашу проблему
stann1,

36

Спираючись на інші відповіді, я написав цей помічник, який виконує завдання, включаючи приклад використання:

public static class Helper
{
    public static List<T> RawSqlQuery<T>(string query, Func<DbDataReader, T> map)
    {
        using (var context = new DbContext())
        {
            using (var command = context.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = query;
                command.CommandType = CommandType.Text;

                context.Database.OpenConnection();

                using (var result = command.ExecuteReader())
                {
                    var entities = new List<T>();

                    while (result.Read())
                    {
                        entities.Add(map(result));
                    }

                    return entities;
                }
            }
        }
    }

Використання:

public class TopUser
{
    public string Name { get; set; }

    public int Count { get; set; }
}

var result = Helper.RawSqlQuery(
    "SELECT TOP 10 Name, COUNT(*) FROM Users U"
    + " INNER JOIN Signups S ON U.UserId = S.UserId"
    + " GROUP BY U.Name ORDER BY COUNT(*) DESC",
    x => new TopUser { Name = (string)x[0], Count = (int)x[1] });

result.ForEach(x => Console.WriteLine($"{x.Name,-25}{x.Count}"));

Я планую позбутися цього, як тільки буде додана вбудована підтримка. Згідно з заявою Артура Вікерса з команди EF Core, це є пріоритетом для версії 2.0. Проблема відстежується тут .


приємна відповідь, сподобалась.
sebu

31

У EF Core ви більше не можете виконувати "безкоштовний" необроблений sql. Вам потрібно визначити клас POCO та класу a DbSetдля цього класу. У вашому випадку вам потрібно буде визначити Ранг :

var ranks = DbContext.Ranks
   .FromSql("SQL_SCRIPT OR STORED_PROCEDURE @p0,@p1,...etc", parameters)
   .AsNoTracking().ToList();

Оскільки це буде напевно лише для читання, корисно буде включити .AsNoTracking()дзвінок.

EDIT - Порушення змін у EF Core 3.0:

DbQuery () тепер застарілий, замість нього слід використовувати DbSet () (знову). Якщо у вас є сутність без ключа, тобто вона не потребує первинного ключа, ви можете використовувати метод HasNoKey () :

ModelBuilder.Entity<SomeModel>().HasNoKey()

Більше інформації можна знайти тут


3
Тому я думаю, що мені також доведеться розширити, DbContextщоб включити нову властивість DbSet<Rank> Rank { get; set; }. Які наслідки це матиме зараз стосовно linq? Тобто Не хочемо, що ми тепер зможемо використовувати оператор типу DBContext.Rank.Where(i => i.key == 1), і чи не буде цей оператор реалізований в SQL і тому не вдасться?
Девід Харлоу

Лінк, випромінюваний проти цього набору, повинен бути вирішений в пам'яті. Якщо вам потрібно випустити інше речення WHERE sql, ви повинні включити їх як параметри або створити інший сценарій.
E-Bat

Мій DbSet не має методу "FromSql". Це розширення, якого мені не вистачає?
birwin

1
@birwin, вам потрібно імпортувати простір імен Microsoft.EntityFrameworkCore
E-Bat

20

Ви можете виконати raw sql в EF Core - Додайте цей клас до свого проекту. Це дозволить вам виконувати необроблений SQL і отримувати вихідні результати без необхідності визначати POCO та DBSet. Дивіться https://github.com/aspnet/EntityFramework/isissue/1862#issuecomment-220787464 для оригінального прикладу.

using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.EntityFrameworkCore
{
    public static class RDFacadeExtensions
    {
        public static RelationalDataReader ExecuteSqlQuery(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
        {
            var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>();

            using (concurrencyDetector.EnterCriticalSection())
            {
                var rawSqlCommand = databaseFacade
                    .GetService<IRawSqlCommandBuilder>()
                    .Build(sql, parameters);

                return rawSqlCommand
                    .RelationalCommand
                    .ExecuteReader(
                        databaseFacade.GetService<IRelationalConnection>(),
                        parameterValues: rawSqlCommand.ParameterValues);
            }
        }

        public static async Task<RelationalDataReader> ExecuteSqlQueryAsync(this DatabaseFacade databaseFacade, 
                                                             string sql, 
                                                             CancellationToken cancellationToken = default(CancellationToken),
                                                             params object[] parameters)
        {

            var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>();

            using (concurrencyDetector.EnterCriticalSection())
            {
                var rawSqlCommand = databaseFacade
                    .GetService<IRawSqlCommandBuilder>()
                    .Build(sql, parameters);

                return await rawSqlCommand
                    .RelationalCommand
                    .ExecuteReaderAsync(
                        databaseFacade.GetService<IRelationalConnection>(),
                        parameterValues: rawSqlCommand.ParameterValues,
                        cancellationToken: cancellationToken);
            }
        }
    }
}

Ось приклад того, як його використовувати:

// Execute a query.
using(var dr = await db.Database.ExecuteSqlQueryAsync("SELECT ID, Credits, LoginDate FROM SamplePlayer WHERE " +
                                                          "Name IN ('Electro', 'Nitro')"))
{
    // Output rows.
    var reader = dr.DbDataReader;
    while (reader.Read())
    {
        Console.Write("{0}\t{1}\t{2} \n", reader[0], reader[1], reader[2]);
    }
}

18

Поки, поки не з’явиться щось нове від EFCore, я використовував би команду і відображав її вручну

  using (var command = this.DbContext.Database.GetDbConnection().CreateCommand())
  {
      command.CommandText = "SELECT ... WHERE ...> @p1)";
      command.CommandType = CommandType.Text;
      var parameter = new SqlParameter("@p1",...);
      command.Parameters.Add(parameter);

      this.DbContext.Database.OpenConnection();

      using (var result = command.ExecuteReader())
      {
         while (result.Read())
         {
            .... // Map to your entity
         }
      }
  }

Спробуйте SqlParameter, щоб уникнути ін'єкції Sql.

 dbData.Product.FromSql("SQL SCRIPT");

FromSql не працює з повним запитом. Приклад, якщо ви хочете включити пункт WHERE, він буде ігнорований.

Деякі посилання:

Виконання необроблених SQL-запитів за допомогою Entity Framework Core

Необроблені запити SQL


7

У Core 2.1 ви можете зробити щось подібне:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
       modelBuilder.Query<Ranks>();
}

а потім визначте процедуру SQL, наприклад:

public async Task<List<Ranks>> GetRanks(string value1, Nullable<decimal> value2)
{
    SqlParameter value1Input = new SqlParameter("@Param1", value1?? (object)DBNull.Value);
    SqlParameter value2Input = new SqlParameter("@Param2", value2?? (object)DBNull.Value);

    List<Ranks> getRanks = await this.Query<Ranks>().FromSql("STORED_PROCEDURE @Param1, @Param2", value1Input, value2Input).ToListAsync();

    return getRanks;
}

Таким чином модель рейтингу не буде створена у вашій БД.

Тепер у вашому контролері / дії ви можете зателефонувати:

List<Ranks> gettingRanks = _DbContext.GetRanks(value1,value2).Result.ToListAsync();

Таким чином ви можете викликати Raw SQL Procedure.


Параметри FromSqlможна просто передавати, не створюючи SqlParameterоб'єкт: FromSql($"STORED_PROCEDURE {value1}, {value2}")або FromSql("STORED_PROCEDURE {0}, {1}", value1, value2)(їх буде захищено).
Маджід

7

Ви можете використовувати це (з https://github.com/aspnet/EntityFrameworkCore/issues/1862#issuecomment-451671168 ):

public static class SqlQueryExtensions
{
    public static IList<T> SqlQuery<T>(this DbContext db, string sql, params object[] parameters) where T : class
    {
        using (var db2 = new ContextForQueryType<T>(db.Database.GetDbConnection()))
        {
            return db2.Query<T>().FromSql(sql, parameters).ToList();
        }
    }

    private class ContextForQueryType<T> : DbContext where T : class
    {
        private readonly DbConnection connection;

        public ContextForQueryType(DbConnection connection)
        {
            this.connection = connection;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // switch on the connection type name to enable support multiple providers
            // var name = con.GetType().Name;
            optionsBuilder.UseSqlServer(connection, options => options.EnableRetryOnFailure());

            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Query<T>();
            base.OnModelCreating(modelBuilder);
        }
    }
}

І використання:

    using (var db = new Db())
    {
        var results = db.SqlQuery<ArbitraryType>("select 1 id, 'joe' name");
        //or with an anonymous type like this
        var results2 = db.SqlQuery(() => new { id =1, name=""},"select 1 id, 'joe' name");
    }

6

Додати пакет Nuget - Microsoft.EntityFrameworkCore.Relational

using Microsoft.EntityFrameworkCore;
...
await YourContext.Database.ExecuteSqlCommandAsync("... @p0, @p1", param1, param2 ..)

Це поверне номери рядків як int

Дивіться - https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.relationaldatabasefacadeextensions.executesqlcommand?view=efcore-3.0


3
Будь ласка , зверніть увагу , що це буде повертати тільки число рядків , порушених командою: stackoverflow.com/a/49861799/299756
kalyfe

Саме те, що мені потрібно. Я використовую Microsoft.EntityFrameworkCore 3.1.1 і не можу виконати запит RAW та SP. Щиро дякую за це!
jaysonragasa

5

спробуйте це: (створити метод розширення)

public static List<T> ExecuteQuery<T>(this dbContext db, string query) where T : class, new()
        {
            using (var command = db.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = query;
                command.CommandType = CommandType.Text;

                db.Database.OpenConnection();

                using (var reader = command.ExecuteReader())
                {
                    var lst = new List<T>();
                    var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
                    while (reader.Read())
                    {
                        var newObject = new T();
                        for (var i = 0; i < reader.FieldCount; i++)
                        {
                            var name = reader.GetName(i);
                            PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
                            if (prop == null)
                            {
                                continue;
                            }
                            var val = reader.IsDBNull(i) ? null : reader[i];
                            prop.SetValue(newObject, val, null);
                        }
                        lst.Add(newObject);
                    }

                    return lst;
                }
            }
        }

Використання:

var db = new dbContext();
string query = @"select ID , Name from People where ... ";
var lst = db.ExecuteQuery<PeopleView>(query);

моя модель: (не в DbSet):

public class PeopleView
{
    public int ID { get; set; }
    public string Name { get; set; }
}

випробувано в .netCore 2.2 and 3.0.

Примітка: це рішення має низьку продуктивність


Спробуйте пошук PropertyInfo по імені лише один раз для першого запису та створити масив PropertyInfo [] за індексами стовпців для використання у наступних записах.
Петр Воборник

@AminRostami Гарна робота
себу,

2

Не безпосередньо націлений на сценарій ОП, але оскільки я борюся з цим, я хотів би відмовитись від них. методи, що полегшують виконання необробленого SQL за допомогою DbContext:

public static class DbContextCommandExtensions
{
  public static async Task<int> ExecuteNonQueryAsync(this DbContext context, string rawSql,
    params object[] parameters)
  {
    var conn = context.Database.GetDbConnection();
    using (var command = conn.CreateCommand())
    {
      command.CommandText = rawSql;
      if (parameters != null)
        foreach (var p in parameters)
          command.Parameters.Add(p);
      await conn.OpenAsync();
      return await command.ExecuteNonQueryAsync();
    }
  }

  public static async Task<T> ExecuteScalarAsync<T>(this DbContext context, string rawSql,
    params object[] parameters)
  {
    var conn = context.Database.GetDbConnection();
    using (var command = conn.CreateCommand())
    {
      command.CommandText = rawSql;
      if (parameters != null)
        foreach (var p in parameters)
          command.Parameters.Add(p);
      await conn.OpenAsync();
      return (T)await command.ExecuteScalarAsync();
    }
  }
}

1

Я використовував Dapper, щоб обійти це обмеження Core Entity framework.

IDbConnection.Query

працює або з запитом sql, або із збереженою процедурою з декількома параметрами. До речі, це трохи швидше (див. Еталонні тести )

Дапер легко вивчити. Написати та запустити збережену процедуру з параметрами потрібно 15 хвилин. У будь-якому випадку ви можете використовувати як EF, так і Dapper. Нижче наведено приклад:

 public class PodborsByParametersService
{
    string _connectionString = null;


    public PodborsByParametersService(string connStr)
    {
        this._connectionString = connStr;

    }

    public IList<TyreSearchResult> GetTyres(TyresPodborView pb,bool isPartner,string partnerId ,int pointId)
    {

        string sqltext  "spGetTyresPartnerToClient";

        var p = new DynamicParameters();
        p.Add("@PartnerID", partnerId);
        p.Add("@PartnerPointID", pointId);

        using (IDbConnection db = new SqlConnection(_connectionString))
        {
            return db.Query<TyreSearchResult>(sqltext, p,null,true,null,CommandType.StoredProcedure).ToList();
        }


        }
}

0

Ви також можете використовувати QueryFirst . Як і Дапер, це абсолютно поза межами EF. На відміну від Dapper (або EF), вам не потрібно підтримувати POCO, ви редагуєте SQL SQL в реальному середовищі, і він постійно перевіряється проти БД. Відмова: Я є автором QueryFirst.


0

У моєму випадку використана збережена процедура замість необробленого SQL

Створив клас

Public class School
{
    [Key]
    public Guid SchoolId { get; set; }
    public string Name { get; set; }
    public string Branch { get; set; }
    public int NumberOfStudents  { get; set; }
}

Додано нижче про мій DbContextклас

public DbSet<School> SP_Schools { get; set; }

Для виконання збереженої процедури:

var MySchools = _db.SP_Schools.FromSqlRaw("GetSchools @schoolId, @page, @size ",
              new SqlParameter("schoolId", schoolId),
              new SqlParameter("page", page),
              new SqlParameter("size", size)))
.IgnoreQueryFilters();


0

Це рішення в значній мірі спирається на рішення від @pius. Я хотів додати параметр для підтримки параметрів запиту, щоб полегшити ін'єкцію SQL, і я також хотів зробити це розширенням DbContext DatabaseFacade for Entity Framework Core, щоб зробити його трохи більш інтегрованим.

Спочатку створіть новий клас із розширенням:

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 Car. Мені подобається такий підхід як одне з багатьох можливих рішень. Інші відповіді на цій сторінці посилаються на інші способи вирішення цієї проблеми за допомогою декоратора [NotMapped], який в залежності від вашої ситуації може бути найбільш підходящим підходом.

Зверніть увагу, що код у цьому прикладі, очевидно, більш багатослівний, ніж повинен бути, але я думав, що це зробило приклад зрозумілішим.


-6

За допомогою Entity Framework 6 ви можете виконати щось на зразок нижче

Створити модальний клас як

Public class User
{
        public int Id { get; set; }
        public string fname { get; set; }
        public string lname { get; set; }
        public string username { get; set; }
}

Виконайте команду Raw DQL SQl, як показано нижче:

var userList = datacontext.Database.SqlQuery<User>(@"SELECT u.Id ,fname , lname ,username FROM dbo.Users").ToList<User>();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.