copytodatatable convert consulta linq entity-framework linq-to-sql

convert - Convierta datetime en una cadena formateada dentro de una consulta LINQ to SQL



linq result to datatable (5)

Sé que LINQ to SQL no convierte DateTime en string ya que no hay ToString() en SQL. Pero, ¿cómo puedo convertir el DateTime en una cadena formateada?

Esta es la línea en la siguiente consulta que necesita ayuda:

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

Toda la consulta:

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();

Recibo el siguiente mensaje de error:

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


EDIT: Ahora que entiendo la pregunta, le estoy dando otra oportunidad :)

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();

Sé que es un poco largo, pero ese es el problema con Linq To SQL.

Cuando usa linq, la llamada a la base de datos no se ejecuta hasta que use algo como ToList () o First () que da como resultado objetos reales. Una vez que la primera llamada .First () ejecuta esa llamada a SQL, ahora está trabajando con tipos de .NET y puede usar cosas de DateTime.


Eso es lo que hicimos, agregamos una nueva función a la clase y consultamos la fecha normalmente en la consulta:

[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();

Luego, simplemente puede llamar al campo FormattedDate pasando el formato deseado.

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

O puede definirlo como un campo con solo el getter:

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

En caso de que su clase sea una Entidad, debe declarar un nuevo parcial de esa clase y agregar el campo.

Espero que esto ayude a alguien.


Otra opción es usar SqlFunctions.DateName, su código será así:

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) })

Me ha resultado útil si no desea agregar un nuevo bloque de selección adicional.


Terminé usando la función sql FORMAT ; Aquí hay una versión simplificada de esta implementación:

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

Primero necesitas definir la función en 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)); } }

Luego defínalo como métodos 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); } }

Regístralo en tu DbContext :

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

Y finalmente, puedes llamarlo así:

var x = db.MyItems.Select(i => new { FormattedDate = SqlFunctions.Format(i.MyDate, "MM/dd/yyyy") }).ToArray();


si es una fecha y hora necesita usar .ToShortDateString() . Pero también es necesario declararlo 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();