생성된 값

데이터베이스 열의 값은 다양한 방법으로 생성될 수 있습니다. 기본 키 열은 자주 정수 자동 증가, 다른 열에는 기본값 또는 계산 값 등이 있습니다. 이 페이지에서는 EF Core를 사용하여 구성 값 생성을 위한 다양한 패턴을 자세히 설명합니다.

기본값

관계형 데이터베이스에서 열을 기본값으로 구성할 수 있습니다. 해당 열에 대한 값 없이 행을 삽입하면 기본값이 사용됩니다.

속성에서 기본값을 구성할 수 있습니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Rating)
        .HasDefaultValue(3);
}

기본값을 계산하는 데 사용되는 SQL 조각을 지정할 수도 있습니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

계산 열

대부분의 관계형 데이터베이스에서 열은 일반적으로 다른 열을 참조하는 식을 사용하여 데이터베이스에서 해당 값을 계산하도록 구성할 수 있습니다.

modelBuilder.Entity<Person>()
    .Property(p => p.DisplayName)
    .HasComputedColumnSql("[LastName] + ', ' + [FirstName]");

위의 내용은 데이터베이스에서 가져올 때마다 해당 값이 계산되는 가상 계산 열을 만듭니다. 계산 열을 저장(지속이라고도 함)으로 지정할 수도 있습니다. 즉, 행의 모든 업데이트에서 계산되고 일반 열과 함께 디스크에 저장됩니다.

modelBuilder.Entity<Person>()
    .Property(p => p.NameLength)
    .HasComputedColumnSql("LEN([LastName]) + LEN([FirstName])", stored: true);

기본 키

규칙에 따라 애플리케이션에서 값을 제공하지 않는 경우 삽입된 엔터티에 대해 생성되는 값을 갖도록 short, int, long 또는 Guid 형식의 복합이 아닌 기본 키가 설정됩니다. 데이터베이스 공급자는 일반적으로 필요한 구성을 처리합니다. 예를 들어 SQL Server 숫자 기본 키는 자동으로 IDENTITY 열로 설정됩니다.

자세한 내용은 특정 상속 매핑 전략에 대한 키지침에 대한 설명서를 참조하세요.

값 생성을 명시적으로 구성

위에서는 EF Core가 기본 키에 대한 값 생성을 자동으로 설정하는 것을 확인했지만 키가 아닌 속성에 대해 동일한 작업을 수행할 수 있습니다. 다음과 같이 삽입된 엔터티에 대해 해당 값이 생성되도록 속성을 구성할 수 있습니다.

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime Inserted { get; set; }
}

마찬가지로 추가 또는 업데이트 시 해당 값이 생성되도록 속성을 구성할 수 있습니다.

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime LastUpdated { get; set; }
}

기본값 또는 계산 열과 달리 값을 생성하는 방법은 지정하지 않습니다. 사용 중인 데이터베이스 공급자에 따라 달라지는 입니다. 데이터베이스 공급자는 일부 속성 형식에 대해 값 생성을 자동으로 설정할 수 있지만 다른 공급자는 값 생성 방법을 수동으로 설정해야 할 수 있습니다.

예를 들어 SQL Server GUID 속성이 기본 키로 구성된 경우 공급자는 알고리즘을 사용하여 최적의 순차 GUID 값을 생성하는 값 생성 클라이언트 쪽을 자동으로 수행합니다. 그러나 DateTime 속성을 지정해 ValueGeneratedOnAdd 도 아무런 효과가 없습니다(DateTime 값 생성은 아래 섹션 참조).

마찬가지로 추가 또는 업데이트 시 생성되고 동시성 토큰으로 표시된 바이트[] 속성은 rowversion 데이터 형식으로 설정되므로 데이터베이스에서 값이 자동으로 생성됩니다. 그러나 ValueGeneratedOnAdd를 지정해도 아무런 효과가 없습니다.

지원하는 특정 값 생성 기술에 대한 공급자 설명서를 참조하세요. SQL Server 값 생성 설명서는 여기에서 찾을 수 있습니다.

날짜/시간 값 생성

일반적인 요청은 행이 처음 삽입된 시간(추가 시 생성된 값) 또는 마지막으로 업데이트된 시점(추가 또는 업데이트 시 생성된 값)에 대한 날짜/시간을 포함하는 데이터베이스 열을 포함하는 것입니다. 이 작업을 수행하기 위한 다양한 전략이 있으므로 EF Core 공급자는 일반적으로 날짜/시간 열에 대해 값 생성을 자동으로 설정하지 않으므로 직접 구성해야 합니다.

만들기 타임스탬프

행의 생성 타임스탬프를 갖도록 날짜/시간 열을 구성하는 것은 일반적으로 적절한 SQL 함수를 사용하여 기본값을 구성하는 문제입니다. 예를 들어 SQL Server 다음을 사용할 수 있습니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

여러 개가 있을 수 있으므로 적절한 함수를 선택해야 합니다(예: GETDATE()GETUTCDATE()).

타임스탬프 업데이트

저장된 계산 열은 마지막으로 업데이트된 타임스탬프를 관리하는 데 적합한 솔루션처럼 보이지만 데이터베이스는 일반적으로 계산 열의 GETDATE()와 같은 함수를 지정할 수 없습니다. 또는 데이터베이스 트리거를 설정하여 동일한 효과를 얻을 수 있습니다.

CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;

    UPDATE B
    SET LastUpdated = GETDATE()
    FROM dbo.Blogs AS B
    INNER JOIN INSERTED AS I
        ON B.BlogId = I.BlogId
END

트리거를 만드는 방법에 대한 자세한 내용은 마이그레이션에서 원시 SQL 사용에 대한 설명서를 참조하세요.

값 생성 재정의

속성은 값 생성을 위해 구성되지만 대부분의 경우 여전히 명시적으로 값을 지정할 수 있습니다. 실제로 작동하는지 여부는 구성된 특정 값 생성 메커니즘에 따라 달라집니다. 열의 기본값을 사용하는 대신 명시적 값을 지정할 수 있지만 계산 열에서는 동일한 작업을 수행할 수 없습니다.

명시적 값으로 값 생성을 재정의하려면 속성을 해당 속성의 형식에 대한 CLR 기본값이 아닌 값(string의 경우 null, int의 경우 0, Guid의 경우 Guid.Empty 등)으로 설정하면 됩니다.

참고 항목

SQL SERVER IDENTITY에 명시적 값을 삽입하려고 하면 기본적으로 실패합니다. 해결 방법은 다음 문서를 참조하세요.

추가 또는 업데이트 시 생성된 값으로 구성된 속성에 대한 명시적 값을 제공하려면 다음과 같이 속성을 구성해야 합니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property(b => b.LastUpdated)
        .ValueGeneratedOnAddOrUpdate()
        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);
}

값 생성 없음

위에서 설명한 것과 같은 특정 시나리오 외에도 속성에는 일반적으로 값 생성이 구성되지 않습니다. 즉, 데이터베이스에 저장할 값을 항상 제공하는 것은 애플리케이션에 달려 있습니다. 이 값은 컨텍스트에 추가되기 전에 새 엔터티에 할당되어야 합니다.

그러나 경우에 따라 규칙에 의해 설정된 값 생성을 사용하지 않도록 설정할 수 있습니다. 예를 들어 int 형식의 기본 키는 일반적으로 암시적으로 value-generated-on-add(예: SQL Server ID 열)로 구성됩니다. 다음을 통해 이 기능을 사용하지 않도록 설정할 수 있습니다.

public class Blog
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int BlogId { get; set; }

    public string Url { get; set; }
}