9

この列をデータベースのPERSISTEDCOMPUTED列と同様にするにはどうすればよいですか?

私の現在の試み(シードにnullが含まれるすべてのCompCol行をロードします):

    public class Call
    {
        public Call()
        {
        }

        [Key]
        public int Id { get; set; }

        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public string CompCol
        {
            get
            {
                return "ABC-" + Convert.ToString(Id).PadLeft(5, '0');
            }
            protected set {}
        }
}
4

3 に答える 3

9

私が見つけた解決策は次のとおりでした:

  1. 自動移行がオフになっていることを確認してください。これは、VSがスクリプト(流暢なAPIコード)を生成して、実行するだけでなく、さらにカスタマイズできるようにするためです。したがって、構成クラスでは:

    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }
    
  2. フィールドをクラスに追加し、そのように計算されたものとして設定します。計算フィールドに書き込むことができないため、セッターはプライベートです。

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public string BreakdownNo { get; private set; }
    
  3. 次にadd-migration [xyz-name]、パッケージマネージャーコンソールでを実行して移行コードを生成します。このコードは、指定された名前の移行フォルダーの下に表示されます。

  4. 移行内でコードをコメントアウトし、次のUp()ようにカスタムSQLを追加します。

    public override void Up()
    {
        //AddColumn("dbo.Calls", "BreakdownNo", c => c.String());
        Sql("ALTER TABLE dbo.Calls ADD BreakdownNo AS ('BD'+RIGHT('00000'+ CAST(Id AS VARCHAR), 6))");
    }
    
  5. update-databasePMでを実行すると、計算列が適切に追加されます。

追記:数式が間違っている場合は、移行を元に戻してからupdate-database -targetMigration: [name of migration to go back to]別の手順を実行add-migration nameし、そこで数式を修正して、update-databaseで終了する必要があります。より良い方法があるかもしれませんが、これは私が見つけて使用したものです。

しかし、私はまだフィールドを持続させる方法を見つけられませんでした。

于 2013-01-22T11:02:50.287 に答える
1

そのようにSQLを呼び出さないのはなぜですか?

public class demo
{
    void demoMethod()
    {
        Model1 model = new Model1();//Model1 : DbContext
        model.Database.ExecuteSqlCommand("alter table Results drop column Total; alter table Results add Total AS (Arabic + English + Math + Science)");
    }
}
于 2017-08-04T08:39:05.893 に答える
0

受け入れられた回答で提案された方法を使用して、私はいくつかの問題に遭遇しました。私は私のために働いた代替ソリューションを提供します。

このクエリの実行中にエラーが発生しました:

oDb.LogEntries.SingleOrDefault(Function(LogEntry) LogEntry.LogTime = dDate)

エラーメッセージ:

'LogEntry'の'MinutesOffline'プロパティを'System.Int32'値に設定できませんでした。このプロパティは、タイプ'System.Single'のnull以外の値に設定する必要があります。

ご覧のとおり、EF6.2はプロパティに値を書き込もうとしています。これがEFが内部的に書き込みを試みたためかどうかPrivate Setはわかりません。それはほとんどそれのようです。しかし、最終的な結果は重要です。ステートメントは失敗します。

列をに設定する代わりにDatabaseGeneratedOption.Computed、私はそれを完全に無視することになりました:Builder.Entity(Of LogEntry).Ignore(Function(LogEntry) LogEntry.MinutesOffline)

これにより、読み取り専用プロパティを作成できました。

Public ReadOnly Property MinutesOffline As Single
  Get
    Return IIf(Me.Scale < 1, 5, 0)
  End Get
End Property

また、生成された移行の行をコメントアウトする必要がないという追加の利点もあります。

まだカスタムSql()呼び出しを行う必要がありますUp()

ALTER TABLE [LogEntries] ADD [MinutesOffline] AS (IIF([Scale] < 1, 5, 0)) PERSISTED

...そしてPERSISTEDキーワードはここで機能します。これは、永続化された計算列になります。

YMMV

- 編集 -

キャストエラーが発生した理由がわかりました。それは移行とは何の関係もなく、私のコードとは何の関係もありませんでした。作成時に計算列を適切にキャストしていませんでした:

ALTER TABLE [LogEntries] ADD [MinutesOffline] AS (IIF([Scale] < 1, 5, 0)) PERSISTED

そのための適切な構文は次のとおりです。

ALTER TABLE [LogEntries] ADD [MinutesOffline] AS (CAST((IIF([Scale] < 1, 5, 0)) AS REAL)) PERSISTED

したがって、私はIgnore()呼び出しを元に戻し、受け入れられた回答で提案された方法にすべてを切り替えました。

支援のためのJotaBeへの帽子のヒント。

于 2018-05-03T10:13:33.970 に答える