Преобразование даты и времени в форматированную строку внутри запроса LINQ to SQL - PullRequest
20 голосов
/ 03 ноября 2011

Я знаю, что LINQ to SQL не конвертирует DateTime в string, поскольку в SQL нет ToString().Но как мне преобразовать DateTime в форматированную строку?

Это строка в следующем запросе, которая нуждается в помощи:

StartDate = string.Format("{0:dd.MM.yy}", p.StartDate)

Весь запрос:

var offer = (from p in dc.CustomerOffer
             join q in dc.OffersInBranch
             on p.ID equals q.OfferID
             where q.BranchID == singleLoc.LocationID
             let value = (p.OriginalPrice - p.NewPrice) * 100 / p.OriginalPrice
             orderby value descending
             select new Offer()
             {
                 Title = p.OfferTitle,
                 Description = p.Description,
                 BestOffer = value,
                 ID = p.ID,
                 LocationID = q.BranchID,
                 LocationName = q.CustomerBranch.BranchName,
                 OriginalPrice = SqlFunctions.StringConvert((decimal)p.OriginalPrice),
                 NewPrice = SqlFunctions.StringConvert((decimal)p.NewPrice),
                 StartDate = string.Format("{0:dd.MM.yy}", p.StartDate)
             }).First();

Я получаю следующее сообщение об ошибке:

LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.

Ответы [ 5 ]

26 голосов
/ 10 апреля 2014

Другой вариант - использование SqlFunctions.DateName, ваш код будет выглядеть следующим образом:

var offer = (from p in dc.CustomerOffer
                 join q in dc.OffersInBranch
                     on p.ID equals q.OfferID
                 where q.BranchID == singleLoc.LocationID
                 let value = (p.OriginalPrice - p.NewPrice) * 100 / p.OriginalPrice
                 orderby value descending
                 select new
                 {
                     Title = p.OfferTitle,
                     Description = p.Description,
                     BestOffer=value,
                     ID=p.ID,
                     LocationID=q.BranchID,
                     LocationName=q.CustomerBranch.BranchName,
                     OriginalPrice=SqlFunctions.StringConvert((decimal)p.OriginalPrice),
                     NewPrice=SqlFunctions.StringConvert((decimal)p.NewPrice),
                     StartDate= SqlFunctions.DateName("day",p.StartDate) + "/" + SqlFunctions.DateName("month",p.StartDate) + "/" +  SqlFunctions.DateName("year",p.StartDate)

                 })

Мне показалось полезным, если вы не хотите добавлять дополнительный блок select new.

13 голосов
/ 03 ноября 2011

РЕДАКТИРОВАТЬ: Теперь, когда я понимаю вопрос, я даю ему еще один выстрел:)

var offer = (from p in dc.CustomerOffer
                     join q in dc.OffersInBranch
                         on p.ID equals q.OfferID
                     where q.BranchID == singleLoc.LocationID
                     let value = (p.OriginalPrice - p.NewPrice) * 100 / p.OriginalPrice
                     orderby value descending
                     select new
                     {
                         Title = p.OfferTitle,
                         Description = p.Description,
                         BestOffer=value,
                         ID=p.ID,
                         LocationID=q.BranchID,
                         LocationName=q.CustomerBranch.BranchName,
                         OriginalPrice=SqlFunctions.StringConvert((decimal)p.OriginalPrice),
                         NewPrice=SqlFunctions.StringConvert((decimal)p.NewPrice),
                         StartDate=p.StartDate

                     })
                     .ToList()
                     .Select(x => new Offer()
                     {
                         Title = x.OfferTitle,
                         Description = x.Description,
                         BestOffer=value,
                         ID=x.ID,
                         LocationID=x.BranchID,
                         LocationName=x.CustomerBranch.BranchName,
                         OriginalPrice=x.OriginalPrice,
                         NewPrice=x.NewPrice,
                         StartDate=x.StartDate.ToString("dd.MM.yy")
                     }).First();

Я знаю, что это немного долго, но это проблема с Linq To SQL.

Когда вы используете linq, вызов базы данных не будет выполнен, пока вы не используете что-то вроде ToList () или First (), которое приводит к фактическим объектам.После того, как этот вызов SQL выполнен первым вызовом .First (), вы теперь работаете с типами .NET и можете использовать материал DateTime.

0 голосов
/ 27 декабря 2018

Я закончил с использованием функции sql FORMAT; Вот упрощенная версия этой реализации:

https://weblogs.asp.net/ricardoperes/registering-sql-server-built-in-functions-to-entity-framework-code-first

Сначала вам нужно определить функцию в EF:

public class FormatFunctionConvention : IStoreModelConvention<EdmModel>
{
    public void Apply(EdmModel item, DbModel model)
    {
        var payload = new EdmFunctionPayload
        {
            StoreFunctionName = "FORMAT",
            Parameters = new[] {
                FunctionParameter.Create("value", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.DateTime), ParameterMode.In),
                FunctionParameter.Create("format", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), ParameterMode.In)
            },
            ReturnParameters = new[] {
                FunctionParameter.Create("result", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), ParameterMode.ReturnValue)
            },
            Schema = "dbo",
            IsBuiltIn = true
        };

        item.AddItem(EdmFunction.Create("FORMAT", "CodeFirstDatabaseSchema", item.DataSpace, payload, null));
    }
}

Затем определите его как методы C #:

public static class SqlFunctions
{
    [DbFunction("CodeFirstDatabaseSchema", "FORMAT")]
    public static String Format(this DateTime value, string format)
    {
        return value.ToString(format);
    }

    [DbFunction("CodeFirstDatabaseSchema", "FORMAT")]
    public static String Format(this DateTime? value, string format)
    {
        return value?.ToString(format);
    }
}

Зарегистрируйте его в своем DbContext:

public class SqlDb : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Conventions.Add(new FormatFunctionConvention());
    }
}

И, наконец, вы можете назвать это так:

var x = db.MyItems.Select(i => new { FormattedDate = SqlFunctions.Format(i.MyDate, "MM/dd/yyyy") }).ToArray();
0 голосов
/ 12 мая 2017

Это то, что мы сделали, мы добавили новую функцию в класс и запросили дату как обычно в запросе:

[ComplexType]
public class Offer
{    
    public DateTime StartDate 
    {
        get;
        set;
    }

   public String Title
   {
       get;
       set;
   }

   /*Other fields*/      
   .
   .
   .


    public string FormattedDate(string format)
    {
        return Date.ToString(format);
    }
}



var offer = (from p in dc.CustomerOffer
         join q in dc.OffersInBranch
         on p.ID equals q.OfferID
         where q.BranchID == singleLoc.LocationID
         let value = (p.OriginalPrice - p.NewPrice) * 100 / p.OriginalPrice
         orderby value descending
         select new Offer()
         {
             Title = p.OfferTitle,
             Description = p.Description,
             BestOffer = value,
             ID = p.ID,
             LocationID = q.BranchID,
             LocationName = q.CustomerBranch.BranchName,
             OriginalPrice = SqlFunctions.StringConvert((decimal)p.OriginalPrice),
             NewPrice = SqlFunctions.StringConvert((decimal)p.NewPrice),
             StartDate = p.StartDate
         }).First();

Затем вы можете просто вызвать поле FormattedDate, передавая желаемый формат.

edit1.Text = offer.FormattedDate("dd.MM.yy");

Или можете определить его как поле с помощью только получателя:

    public string FormattedDate
                {
                   get { return Date.ToString("dd.MM.yy") };
                }

 edit1.Text = offer.FormattedDate;

Если ваш класс является сущностью, вам нужно объявить новый фрагмент этого класса и добавить поле.

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 03 января 2013

если это дата и время, вам нужно использовать .ToShortDateString().Но вам также нужно объявить это как AsEnumerable ().

var offer = (from p in dc.CustomerOffer.AsEnumerable()
                 join q in dc.OffersInBranch
                     on p.ID equals q.OfferID
                 where q.BranchID == singleLoc.LocationID
                 let value = (p.OriginalPrice - p.NewPrice) * 100 / p.OriginalPrice
                 orderby value descending
                 select new
                 {
                     Title = p.OfferTitle,
                     Description = p.Description,
                     BestOffer=value,
                     ID=p.ID,
                     LocationID=q.BranchID,
                     LocationName=q.CustomerBranch.BranchName,
                     OriginalPrice=SqlFunctions.StringConvert((decimal)p.OriginalPrice),
                     NewPrice=SqlFunctions.StringConvert((decimal)p.NewPrice),
                     StartDate=p.StartDate

                 })
                 .ToList()
                 .Select(x => new Offer()
                 {
                     Title = x.OfferTitle,
                     Description = x.Description,
                     BestOffer=value,
                     ID=x.ID,
                     LocationID=x.BranchID,
                     LocationName=x.CustomerBranch.BranchName,
                     OriginalPrice=x.OriginalPrice,
                     NewPrice=x.NewPrice,
                     StartDate=x.StartDate.ToShortDateString()
                 }).First();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...