ASP. NET C# MVC Entity Framework - PullRequest
       32

ASP. NET C# MVC Entity Framework

0 голосов
/ 11 февраля 2020

Я учусь ASP. NET MVC, и я застрял в создании сложных SQL с использованием Entity Framework - это не так сложно, но может стать сложным.

Мой обычный ASP. NET C# веб-форма выглядит следующим образом, и я хочу преобразовать ее в ASP. NET MVC и с Entity Framework.

string date = Request.QueryString["date"] ?? "";
string strWhere = "";
string sqlTop = "20";

DateTime temp;

if (DateTime.TryParse(date, out temp))
{
    strWhere = "WHERE CAST(NewsDate AS date)='" + temp.ToString("yyyy-MM-dd") + "'";
    sqlTop = "50";
}

using (SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["NewsDB"].ConnectionString))
{
    con.Open();
    string selectSql = @"SELECT TOP " + sqlTop + @" *
                              , (SELECT TOP 1 FileName 
                                 FROM NewsImage
                                 WHERE NewsGuid = N.NewsGuid
                                 ORDER BY FileOrder ASC) AS FileName
                        FROM    News N " + strWhere + @"
                        ORDER BY N.NewsDate DESC";

    using (SqlCommand selectCmd = new SqlCommand(selectSql, con))
    {
        using (SqlDataReader selectDr = selectCmd.ExecuteReader())
        {
            while (selectDr.Read())
            {
                //My Output logic goes here
            }
        }
    }
}

Мой вопрос: как достичь этого типа SQL, используя Entity Framework.

Я создал объекты и настроил DbContext, используя подход, основанный на базе данных.

private NewsEntities db = new NewsEntities();

У меня есть две базы данных таблицы: News & NewsImage Одиночные новости могут иметь несколько изображений (1-N)

Я пытался достичь чего-то вроде этого:

NewsClass

public class NewsClass
    {
        public News NewsDetails { get; set; }
        public NewsImage NewsImages { get; set; }
    }

Модель: News

public partial class News
{
    public int Id { get; set; }
    public System.Guid NewsGuid { get; set; }
    public string Heading { get; set; }
    public string Text { get; set; }
    public string Author { get; set; }
    public System.DateTime NewsDate { get; set; }
}

Модель: NewsImage

public partial class NewsImage
{
    public int Id { get; set; }
    public System.Guid NewsGuid { get; set; }
    public string FileName { get; set; }
    public int FileOrder { get; set; }
}

Контроллер:

var newsList = from n in news
join img in newsImages on n.NewsGuid equals img.NewsGuid into table1
from img in table1.DefaultIfEmpty()
select new NewsClass { NewsDetails = n, NewsImage = img };

отсюда я застрял ... "выберите топ 1" в подзапросе, как добиться этого

Становиться лучше ... Теперь я сделал что-то вроде этого:

var newsImages = db.NewsImages.OrderBy(n => n.NewsGuid).OrderBy(n => n.FileOrder).Where(n => n.FileOrder == 10);
var allNews = db.News.OrderByDescending(n => n.NewsDate).Take(sqlTop);

if (validDate)
    allNews = allNews.Where(n => n.NewsDate.Year == newsDate.Year && n.NewsDate.Month == newsDate.Month && n.NewsDate.Day == newsDate.Day);

Теперь мне нужно объединить эти два объекта "new sImages "и" allNews "в один список" newsList ".

Как мне объединить два списка запросов allNews и newsImages в один список, например:

select new NewsList
{
    NewsGuid = n.NewsGuid,
    Heading = n.Heading,
    FileName = ni.FileName
}).Take(sqlTop).ToList<NewsList>();

1 Ответ

3 голосов
/ 11 февраля 2020

Основным преимуществом Entity Framework (и других ORM) является то, что вам больше не нужно писать необработанные SQL для достижения ваших целей. OR mapper создает удобную для использования структуру объектов, которую вы можете использовать для выполнения запросов.

В вашем случае вы будете делать что-то вроде:

string date = Request.QueryString["date"] ?? "";
int sqlTop = 20;

DateTime? newsDate = null;

if (DateTime.TryParse(date, out DateTime temp))
{
    newsDate = temp;
    sqlTop = 50;
}

using (NewsEntities db = new NewsEntities())
{
    // grab the "NewsClass" entries - include the "NewsDetails" and
    // "NewsImage" navigation property
    var query = db.NewsClass
                  .Include(n => n.NewsDetails);
                  .Include(n => n.NewsImage);

    // if you have a valid date - use that to refine the query
    if (newsDate.HasValue)
    {
        query = query.Where(n => n.NewsDetails.NewsDate == newsDate.Value);
    }

    // order by NewsDate, and select only "sqlTop" entries 
    query = query.OrderByDescending(n => n.NewsDetails.NewsDate
                 .Take(sqlTop);

    // now you can iterate over the "News" objects returned from the query
    foreach(News n in query)
    {
       // get the first image from navigation property
       var firstImage = n.NewsImage
                         .OrderBy(img => img.FileOrder)
                         .FirstOrDefault();

       // do whatever you want with your news - output what you need
    }
}
...