Programing

EF Code First의 계산 된 열

lottogame 2020. 11. 1. 17:15
반응형

EF Code First의 계산 된 열


데이터베이스에서 (행 합계)-(행 합계 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에 문제가 없습니다.


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을 참조하십시오 .


한 가지 방법은 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

I would go about this by just using a view model. For example rather than have the FirstTable class as a db entity would you not be better just having a view model class called FirstTable and then have a function that is used to return this class that would include the calculated sum? For example your class would just be:

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

And then you would have a function that you call that returns the calculated sum:

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;
}

Basically the same as an SQL view and as @Linus mentioned I don't think it would be a good idea keeping the computed value in the database. Just some thoughts.


I stumbled across this question when trying to have an EF Code First model with a string column "Slug", be derived from another string column "Name". The approach I took was slightly different but worked out well so I will share it here.

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; }

What is nice about this approach is you get the automatic slug generation, while never exposing the slug setter. The .ToUrlSlug() method isn't the important part of this post, you could use anything in its place to do the work you need done. Cheers!

참고URL : https://stackoverflow.com/questions/15585330/calculated-column-in-ef-code-first

반응형