데이터베이스에서 (행 합계)-(행 합계 b)로 계산 된 데이터베이스에 하나의 열이 있어야합니다. 코드 우선 모델을 사용하여 데이터베이스를 만들고 있습니다.
내가 의미하는 바는 다음과 같습니다.
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에는 개인 setter에 문제가 없습니다.
참고 : EF .NET Core의 경우 HasDatabaseGeneratedOption이 없기 때문에 ValueGeneratedOnAddOrUpdate 를 사용해야 합니다. 예 :
modelBuilder.Entity<Income>().Property(t => t.Summ)
.ValueGeneratedOnAddOrUpdate()
답변
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을 참조하십시오 .
답변
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)
}
답변
한 가지 방법은 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가 언급했듯이 데이터베이스에 계산 된 값을 유지하는 것이 좋은 생각이 아니라고 생각합니다. 약간의 생각.
답변
문자열 열 “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 () 메서드는이 게시물의 중요한 부분이 아닙니다. 필요한 작업을 수행하기 위해 그 자리에서 무엇이든 사용할 수 있습니다. 건배!