データベースによって(行の合計)-(rowsbの合計)として計算されるデータベースの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でこれを達成するにはどうすればよいですか?
データベーステーブルに 計算列 を作成できます。 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にはプライベートセッターに関する問題はありません。
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 */ }
}
}
参照:
2019年の時点で、EFコアを使用すると、流れるようなAPIを使用してクリーンな方法で列を計算できます。
DisplayName
が定義する計算列であると仮定すると、通常はプロパティを定義する必要があります。場合によっては、プライベートプロパティアクセサを使用してプロパティを割り当てないようにする必要があります
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// this will be computed
public string DisplayName { get; private set; }
}
次に、モデルビルダーで、列定義でアドレス指定します。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.Property(p => p.DisplayName)
// here is the computed query definition
.HasComputedColumnSql("[LastName] + ', ' + [FirstName]");
}
詳細については、 [〜#〜] msdn [〜#〜] をご覧ください。
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オブジェクト内で実行できますpublic class FirstTable
、しかし私は思うそれは良い設計ではないので、私は提案しません。
別の方法は、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
これについては、ビューモデルを使用するだけです。たとえば、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が言及したように、計算された値をデータベースに保持することは良い考えではないと思います。いくつかの考え。