140

EntityFramework4.1で導入されたDbContextおよびCodeFirstAPIを使用しています。

データモデルstringは、やなどの基本的なデータ型を使用しますDateTime。場合によっては使用している唯一のデータ注釈はですが[Required]、それはどのDateTimeプロパティにもありません。例:

public virtual DateTime Start { get; set; }

DbContextサブクラスも単純で、次のようになります。

public class EventsContext : DbContext
{
    public DbSet<Event> Events { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Event>().ToTable("Events");
    }
}

イニシャライザは、モデルの日付を今年または来年の適切な値に設定します。

ただし、初期化子を実行すると、次の場所でこのエラーが発生しcontext.SaveChanges()ます。

datetime2データ型をdatetimeデータ型に変換すると、値が範囲外になりました。ステートメントは終了されました。

すべてがとても単純なので、なぜこれが起こっているのかまったくわかりません。編集するedmxファイルがないため、修正方法もわかりません。

何か案は?

4

15 に答える 15

194

StartがSqlDateTime.MinValue(1753年1月1日)以上であることを確認する必要があります。デフォルトでは、StartはDateTime.MinValue(0001年1月1日)と同じです。

于 2011-05-18T21:12:11.793 に答える
24

単純。最初にコードで、DateTimeのタイプをDateTime?に設定します。したがって、データベースでnull許容のDateTime型を操作できます。エンティティの例:

public class Alarme
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public DateTime? DataDisparado { get; set; }//.This allow you to work with nullable datetime in database.
        public DateTime? DataResolvido { get; set; }//.This allow you to work with nullable datetime in database.
        public long Latencia { get; set; }

        public bool Resolvido { get; set; }

        public int SensorId { get; set; }
        [ForeignKey("SensorId")]
        public virtual Sensor Sensor { get; set; }
    }
于 2015-05-11T16:27:05.653 に答える
23

場合によっては、DateTime.MinValue(または同等にdefault(DateTime))が不明な値を示すために使用されます。

この単純な拡張方法は、このような状況を処理するのに役立ちます。

public static class DbDateHelper
{
    /// <summary>
    /// Replaces any date before 01.01.1753 with a Nullable of 
    /// DateTime with a value of null.
    /// </summary>
    /// <param name="date">Date to check</param>
    /// <returns>Input date if valid in the DB, or Null if date is 
    /// too early to be DB compatible.</returns>
    public static DateTime? ToNullIfTooEarlyForDb(this DateTime date)
    {
        return (date >= (DateTime) SqlDateTime.MinValue) ? date : (DateTime?)null;
    }
}

使用法:

 DateTime? dateToPassOnToDb = tooEarlyDate.ToNullIfTooEarlyForDb();
于 2013-10-25T07:42:43.717 に答える
13

特定のモデリングの懸念事項に適している場合は、フィールドをnull許容にすることができます。nullの日付は、デフォルト値のようにSQLDateTime型の範囲内にない日付に強制変換されません。別のオプションは、別のタイプに明示的にマップすることです。

.HasColumnType("datetime2")
于 2011-05-19T04:36:58.127 に答える
13

この質問はかなり古く、すでに素晴らしい答えがありますが、この問題を解決するための3つの異なるアプローチを説明するもう1つを追加する必要があると思いました。

最初のアプローチ

DateTimeプロパティpublic virtual DateTime Start { get; set; }datetime2テーブルの対応する列に明示的にマップします。デフォルトでは、EFはそれをにマップするためdatetimeです。

これは、流暢なAPIまたはデータ注釈によって実行できます。

  1. Fluent API

    DbContextクラスでは、プロパティをオーバーライドOnModelCreatingして構成しますStart(説明の理由から、これはEntityClassクラスのプロパティです)。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Configure only one property 
        modelBuilder.Entity<EntityClass>()
            .Property(e => e.Start)
            .HasColumnType("datetime2");
    
       //or configure all DateTime Preperties globally(EF 6 and Above)
        modelBuilder.Properties<DateTime>()
            .Configure(c => c.HasColumnType("datetime2"));
    }
    
  2. データ注釈

    [Column(TypeName="datetime2")]
    public virtual DateTime Start { get; set; }
    

2番目のアプローチ

EntityClassコンストラクターでデフォルト値に初期化します。これは、エンティティをデータベースに保存する前にStart、何らかの理由での値が設定されていないかのように適切です。startは常にデフォルト値を持ちます。デフォルト値がSqlDateTime.MinValueStart以上であることを確認してください(1753年1月1日から9999年12月31日まで)

public class EntityClass
{
    public EntityClass()
    {
        Start= DateTime.Now;
    }
    public DateTime Start{ get; set; }
}

3番目のアプローチ

nullStart許容型にする-後のDateTime -?DateTime

public virtual DateTime? Start { get; set; }

詳細については、この投稿をお読みください

于 2015-01-21T11:37:30.097 に答える
8

DateTimeプロパティがデータベースでnull許容の場合は、関連付けられたオブジェクトプロパティに必ず使用してください。そうしないと、SQL日時タイプが処理できる範囲外の未割り当ての値がDateTime?EFによって渡されます。DateTime.MinValue

于 2015-01-27T18:47:41.997 に答える
8

私の解決策は、すべての日時列をdatetime2に切り替え、新しい列にはdatetime2を使用することでした。つまり、EFでデフォルトでdatetime2を使用するようにします。これをコンテキストのOnModelCreatingメソッドに追加します。

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

それはすべてのDateTimeとDateTimeを取得しますか?すべてのエンティティのプロパティ。

于 2016-08-29T10:37:26.320 に答える
3

コンストラクターでStartプロパティを初期化します

Start = DateTime.Now;

これは、CodeFirstを使用してASP.Net Identity FrameworkのUsersテーブル(AspNetUsers)にいくつかの新しいフィールドを追加しようとしたときに機能しました。IdentityModels.csのClass-ApplicationUserを更新し、DateTimeタイプのフィールドlastLoginを追加しました。

public class ApplicationUser : IdentityUser
    {
        public ApplicationUser()
        {
            CreatedOn = DateTime.Now;
            LastPassUpdate = DateTime.Now;
            LastLogin = DateTime.Now;
        }
        public String FirstName { get; set; }
        public String MiddleName { get; set; }
        public String LastName { get; set; }
        public String EmailId { get; set; }
        public String ContactNo { get; set; }
        public String HintQuestion { get; set; }
        public String HintAnswer { get; set; }
        public Boolean IsUserActive { get; set; }

        //Auditing Fields
        public DateTime CreatedOn { get; set; }
        public DateTime LastPassUpdate { get; set; }
        public DateTime LastLogin { get; set; }
    }
于 2014-08-09T17:16:08.273 に答える
2

ユーザー@andygjpの回答に基づいて、基本Db.SaveChanges()メソッドをオーバーライドし、SqlDateTime.MinValueとSqlDateTime.MaxValueの間にない日付をオーバーライドする関数を追加するとよいでしょう。

これがサンプルコードです

public class MyDb : DbContext
{
    public override int SaveChanges()
    {
        UpdateDates();
        return base.SaveChanges();
    }

    private void UpdateDates()
    {
        foreach (var change in ChangeTracker.Entries().Where(x => (x.State == EntityState.Added || x.State == EntityState.Modified)))
        {
            var values = change.CurrentValues;
            foreach (var name in values.PropertyNames)
            {
                var value = values[name];
                if (value is DateTime)
                {
                    var date = (DateTime)value;
                    if (date < SqlDateTime.MinValue.Value)
                    {
                        values[name] = SqlDateTime.MinValue.Value;
                    }
                    else if (date > SqlDateTime.MaxValue.Value)
                    {
                        values[name] = SqlDateTime.MaxValue.Value;
                    }
                }
            }
        }
    }
}

https://stackoverflow.com/a/11297294/9158120のユーザー@sky-devのコメントから取得

于 2019-02-18T10:30:38.757 に答える
1

同じ問題が発生しました。私の場合、日付をDateTime.Nowではなくnew DateTime()に設定していました。

于 2016-03-25T20:06:56.220 に答える
0

私の場合、これはエンティティを使用したときに発生し、SQLテーブルのデフォルト値はdatetime == getdate()です。したがって、このフィールドに値を設定するために私が行ったこと。

于 2016-02-27T20:50:24.100 に答える
0

私はデータベースファーストを使用していますが、このエラーが発生したときの解決策は、edmxファイルでProviderManifestToken = "2005"を強制することでした(モデルをSQL Server 2005と互換性のあるものにします)。コードファーストで同様のことが可能かどうかわからない。

于 2017-04-07T20:55:05.927 に答える
0

1行でこれを修正します。

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));

したがって、私のコードでは、次のように追加しました。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}

その1行をDBContextサブクラスオーバーライドvoidOnModelCreatingセクションに追加すると機能するはずです。

于 2019-06-04T12:50:59.767 に答える
0

私の場合、EF6でリファクタリングした後、テストは元のポスターと同じエラーメッセージで失敗しましたが、私のソリューションはDateTimeフィールドとは何の関係もありませんでした。

エンティティを作成するときに必須フィールドがありませんでした。不足しているフィールドを追加すると、エラーはなくなりました。私のエンティティには2つのDateTimeがありますか?フィールドが、それらは問題ではありませんでした。

于 2019-07-29T18:20:46.690 に答える
-1

誰かが私と同じように愚かである場合は、あなたの日付の年を再確認してください。YYMMDD形式のテキストファイルから日付を変換していたので、2020年ではなく0020年の日付を作成していました。明らかなエラーですが、見るのに時間がかかりましたが、本来あるべきよりも見えませんでした。

于 2020-12-02T10:25:04.073 に答える