94

データベースで(行の合計)-(行の合計b)として計算されるデータベースに1つの列が必要です。コードファーストモデルを使用してデータベースを作成しています。

これが私が意味することです:

public class Income {
      [Key]
      public int UserID { get; set; }
      public double inSum { get; set; }
}

public class Outcome {
      [Key]
      public int UserID { get; set; }
      public double outSum { get; set; }
}

public class FirstTable {
      [Key]
      public int UserID { get; set; }
      public double Sum { get; set; } 
      // This needs to be calculated by DB as 
      // ( Select sum(inSum) FROM Income WHERE UserID = this.UserID) 
      // - (Select sum(outSum) FROM Outcome WHERE UserID = this.UserID)
}

EF CodeFirst でこれを達成するにはどうすればよいですか?

4

7 に答える 7

150

データベース テーブルに計算列を作成できます。EF モデルでは、対応するプロパティに次のDatabaseGenerated属性で注釈を付けるだけです。

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public double Summ { get; private set; } 

または流暢なマッピングで:

modelBuilder.Entity<Income>().Property(t => t.Summ)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)

Matija Grcicとコメントで提案されているように、プロパティを作成するprivate setことをお勧めします。おそらく、アプリケーション コードで設定したくないからです。Entity Framework には、プライベート セッターに関する問題はありません。

注: EF .NET Core の場合、HasDatabaseGeneratedOption が存在しないため、ValueGeneratedOnAddOrUpdateを使用する必要があります。

modelBuilder.Entity<Income>().Property(t => t.Summ)
    .ValueGeneratedOnAddOrUpdate()
于 2013-03-23T10:04:42.137 に答える
39
public string ChargePointText { get; set; }

public class FirstTable 
{
    [Key]
    public int UserID { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]      
    public string Summ 
    {
        get { return /* do your sum here */ }
        private set { /* needed for EF */ }
    }
}

参考文献:

于 2013-03-23T10:09:29.737 に答える
4

EF6 では、次のように、計算されたプロパティを無視するようにマッピング設定を構成するだけです。

モデルの get プロパティで計算を定義します。

public class Person
{
    // ...
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName => $"{FirstName} {LastName}";
}

次に、モデル構成で無視するように設定します

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    //...
    modelBuilder.Entity<Person>().Ignore(x => x.FullName)
}
于 2020-03-06T12:00:30.450 に答える
3

1 つの方法は、LINQ を使用することです。

var userID = 1; // your ID
var income = dataContext.Income.First(i => i.UserID == userID);
var outcome = dataContext.Outcome.First(o => o.UserID == userID);
var summ = income.inSumm - outcome.outSumm;

POCO object 内で行うこともできますが、良い設計ではないと思うpublic class FirstTableので、お勧めしません。

もう 1 つの方法は、SQL ビューを使用することです。Entity Framework でビューをテーブルのように読み取ることができます。ビュー コード内では、計算などを実行できます。次のようなビューを作成するだけです

-- not tested
SELECT FirstTable.UserID, Income.inCome - Outcome.outCome
  FROM FirstTable INNER JOIN Income
           ON FirstTable.UserID = Income.UserID
       INNER JOIN Outcome
           ON FirstTable.UserID = Outcome.UserID
于 2013-03-23T09:58:35.380 に答える
1

ビューモデルを使用するだけでこれを実現できます。たとえば、FirstTable クラスを db エンティティとして持つよりも、FirstTable というビュー モデル クラスを持ち、計算された合計を含むこのクラスを返すために使用される関数を持つ方がよいのではないでしょうか? たとえば、クラスは次のようになります。

public class FirstTable {
  public int UserID { get; set; }
  public double Sum { get; set; }
 }

そして、計算された合計を返す関数を呼び出します。

public FirsTable GetNetSumByUserID(int UserId)
{
  double income = dbcontext.Income.Where(g => g.UserID == UserId).Select(f => f.inSum);
  double expenses = dbcontext.Outcome.Where(g => g.UserID == UserId).Select(f => f.outSum);
  double sum = (income - expense);
  FirstTable _FirsTable = new FirstTable{ UserID = UserId, Sum = sum};
  return _FirstTable;
}

基本的に SQL ビューと同じであり、@Linus が述べたように、計算された値をデータベースに保持するのは良い考えではないと思います。ほんの少しの考え。

于 2014-12-08T05:06:54.963 に答える
-1

文字列列 "Slug" を持つ EF Code First モデルを別の文字列列 "Name" から派生させようとしたときに、この質問に出くわしました。私が取ったアプローチは少し異なっていましたが、うまくいきましたので、ここで共有します。

private string _name;

public string Name
{
    get { return _name; }
    set
    {
        _slug = value.ToUrlSlug(); // the magic happens here
        _name = value; // but don't forget to set your name too!
    }
}

public string Slug { get; private set; }

このアプローチの優れている点は、スラッグ セッターを公開することなく、スラッグを自動生成できることです。.ToUrlSlug() メソッドは、この投稿の重要な部分ではありません。必要な作業を行うために、代わりに何でも使用できます。乾杯!

于 2016-04-30T02:56:26.793 に答える