EF6 쿼리 번역기 DateTime.TimeOfDay
을 지원하지 않으며, 오라클 제공자는/상수를 DbFunctions.CreateTime
및 TimeSpan
매개 변수를 지원하지 않습니다.
다른 답변으로 제안 된대로 스토리지를 DateTime
에서 string
으로 전환하기 전에 몇 가지 옵션이 있습니다.
첫째, 당신은 (쿼리 매개 변수) 별도의 변수로 추출 중 한 가지 방법으로 시간 구성 요소를 비교할 수있는 평등 수표 :
var hour = viewmodel.ExecutionTime.Hours;
var minute = viewmodel.ExecutionTime.Minutes;
var second = viewmodel.ExecutionTime.Seconds;
var db0010016 = _idb0010016Rep.FindBy(e =>
e.ExecutionTime.Hour == hour && e.ExecutionTime.Minute == minute && e.ExecutionTime.Second == second)
.FirstOrDefault();
가짜 DateTime
변수 (queryParameter)에 :
var executionTime = DateTime.Today + viewmodel.ExecutionTime;
var db0010016 = _idb0010016Rep.FindBy(e =>
e.ExecutionTime.Hour == executionTime.Hour && e.ExecutionTime.Minute == executionTime.Minute && e.ExecutionTime.Second == executionTime.Second)
.FirstOrDefault();
둘째, 초 단위로 변환 된 시간으로 작업 할 수 있습니다.
var executionTime = (int)viewmodel.ExecutionTime.TotalSeconds;
var db0010016 = _idb0010016Rep.FindBy(e =>
60 * 60 * e.ExecutionTime.Hour + 60 * e.ExecutionTime.Minute + e.ExecutionTime.Second == executionTime)
.FirstOrDefault();
그러나 수동 경향이 매우 짜증나는 오류입니다 모든 일이 당신은 또한 어떤 비교를 수행 할 수 있습니다.
이
public static partial class QueryableExtensions
{
public static IQueryable<T> ConvertTimeSpans<T>(this IQueryable<T> source)
{
var expr = new TimeSpanConverter().Visit(source.Expression);
return source == expr ? source : source.Provider.CreateQuery<T>(expr);
}
class TimeSpanConverter : ExpressionVisitor
{
static readonly Expression<Func<DateTime, int>> ConvertTimeOfDay = dt =>
60 * (60 * dt.Hour + dt.Minute) + dt.Second;
static int ConvertTimespan(TimeSpan ts) =>
60 * (60 * ts.Hours + ts.Minutes) + ts.Seconds;
protected override Expression VisitMember(MemberExpression node)
{
if (node.Type == typeof(TimeSpan))
{
if (node.Member.DeclaringType == typeof(DateTime) && node.Member.Name == nameof(DateTime.TimeOfDay))
return ConvertTimeOfDay.ReplaceParameter(0, base.Visit(node.Expression));
// Evaluate the TimeSpan value, convert and wrap it into closure (to keep non const semantics)
return ConvertTimespan(base.VisitMember(node).Evaluate<TimeSpan>()).ToClosure().Body;
}
return base.VisitMember(node);
}
protected override Expression VisitBinary(BinaryExpression node)
{
if (node.Left.Type == typeof(TimeSpan))
return Expression.MakeBinary(node.NodeType, Visit(node.Left), Visit(node.Right));
return base.VisitBinary(node);
}
}
static T Evaluate<T>(this Expression source) => Expression.Lambda<Func<T>>(source).Compile().Invoke();
static Expression<Func<T>> ToClosure<T>(this T value) =>() => value;
static Expression ReplaceParameter(this LambdaExpression source, int index, Expression target) =>
new ParameterReplacer { Source = source.Parameters[index], Target = target }.Visit(source.Body);
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node) => node == Source ? Target : node;
}
}
그것은 당신의 viewModel.ExecutionTime
유사한 DateTime.TimeOfDay
재산과 TimeSpan
클래스 속성을 변환하는 두 개의 작은 사용자 정의 ExpressionVisitor
클래스를 사용 : 내가 제공 할 수있는 것은 작은 유틸리티 클래스를 제공하는 사용자 정의 확장 방법이야.
지금이 같이 원래 쿼리를 사용해야합니다 :
대신 초 (밀리 초)을 사용하려는 경우
var db0010016 = _idb0010016Rep.GetAll()
.Where(e => e.ExecutionTime.TimeOfDay == viewmodel.ExecutionTime)
.ConvertTimeStamps() // the magic happens here
.FirstOrDefault();
, 당신이 필요로하는 모든 다음과 같이 TimeSpanConverter
클래스의 처음 두 문장을 변경하는 것입니다 :
static readonly Expression<Func<DateTime, int>> ConvertTimeOfDay = dt =>
1000 * (60 * (60 * dt.Hour + dt.Minute) + dt.Second) + dt.Millisecond;
static int ConvertTimespan(TimeSpan ts) =>
1000 * (60 * (60 * ts.Hours + ts.Minutes) + ts.Seconds) + ts.Milliseconds;
첫 번째 코드를 실행할 때 어떤 오류가 발생합니까? –
https://stackoverflow.com/questions/39822588/how-to-convert-datetime-to-timespan-in-entity-framework-query?rq=1의 복제본처럼 보입니다. 그것들을 문자열로 변환하는 것보다 낫다는 것을 확인하십시오! – user2612030