Ustawienie jawne wartości dla wygenerowanych właściwościSetting Explicit Values for Generated Properties

Wygenerowana właściwość jest właściwością, którego wartość jest generowana (albo przez EF lub bazy danych) podczas dodane lub zaktualizowane jednostki.A generated property is a property whose value is generated (either by EF or the database) when the entity is added and/or updated. Zobacz wygenerowanych właściwości Aby uzyskać więcej informacji.See Generated Properties for more information.

Mogą wystąpić sytuacje, w której chcesz ustawić jawną wartość dla wygenerowanej właściwości zamiast plan wygenerowany.There may be situations where you want to set an explicit value for a generated property, rather than having one generated.

Porada

Przykład użyty w tym artykule można zobaczyć w witrynie GitHub.You can view this article's sample on GitHub.

ModelThe model

Model używany w tym artykule zawiera pojedynczy Employee jednostki.The model used in this article contains a single Employee entity.

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }
    public DateTime EmploymentStarted { get; set; }
    public int Salary { get; set; }
    public DateTime? LastPayRaise { get; set; }
}

Zapisywanie jawną wartość podczas DodajSaving an explicit value during add

Employee.EmploymentStarted Skonfigurowano właściwości do wartości generowane przez bazę danych do nowych jednostek (przy użyciu wartości domyślnej).The Employee.EmploymentStarted property is configured to have values generated by the database for new entities (using a default value).

modelBuilder.Entity<Employee>()
    .Property(b => b.EmploymentStarted)
    .HasDefaultValueSql("CONVERT(date, GETDATE())");

Poniższy kod powoduje wstawienie dwóch pracowników do bazy danych.The following code inserts two employees into the database.

  • W pierwszym, zostanie przypisana żadna wartość, aby Employee.EmploymentStarted , dzięki czemu pozostanie ustawioną na wartość domyślną CLR dla DateTime.For the first, no value is assigned to Employee.EmploymentStarted property, so it remains set to the CLR default value for DateTime.
  • Z drugiej ustawimy mają jawne wartości 1-Jan-2000.For the second, we have set an explicit value of 1-Jan-2000.
using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { Name = "John Doe" });
    context.Employees.Add(new Employee { Name = "Jane Doe", EmploymentStarted = new DateTime(2000, 1, 1) });
    context.SaveChanges();

    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name + ", " + employee.EmploymentStarted);
    }
}

Dane wyjściowe pokazują, że bazy danych wygenerowaną wartość dla pierwszego pracownika i użyto naszych jawną wartość dla drugiego.Output shows that the database generated a value for the first employee and our explicit value was used for the second.

1: John Doe, 1/26/2017 12:00:00 AM
2: Jane Doe, 1/1/2000 12:00:00 AM

Jawne wartości w kolumnach tożsamości serwera SQLExplicit values into SQL Server IDENTITY columns

Zgodnie z Konwencją Employee.EmployeeId właściwość jest magazynem generowane IDENTITY kolumny.By convention the Employee.EmployeeId property is a store generated IDENTITY column.

W większości sytuacji to podejście pokazano powyżej będzie działać w przypadku właściwości klucza.For most situations, the approach shown above will work for key properties. Jednakże można wstawić jawnej wartości do programu SQL Server IDENTITY kolumnę, musisz ręcznie włączyć IDENTITY_INSERT przed wywołaniem SaveChanges().However, to insert explicit values into a SQL Server IDENTITY column, you need to manually enable IDENTITY_INSERT before calling SaveChanges().

Uwaga

Mamy zgłoszenie dotyczące funkcji na naszej liście prac, aby to zrobić automatycznie przy użyciu dostawcy programu SQL Server.We have a feature request on our backlog to do this automatically within the SQL Server provider.

using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" });
    context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" });

    context.Database.OpenConnection();
    try
    {
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees ON");
        context.SaveChanges();
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees OFF");
    }
    finally
    {
        context.Database.CloseConnection();
    }


    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name);
    }
}

Dane wyjściowe pokazują, że podane identyfikatory zostały zapisane w bazie danych.Output shows that the supplied ids were saved to the database.

100: John Doe
101: Jane Doe

Ustawianie jawną wartość podczas aktualizacjiSetting an explicit value during update

Employee.LastPayRaise Skonfigurowano właściwości do wartości generowane przez bazę danych podczas aktualizacji.The Employee.LastPayRaise property is configured to have values generated by the database during updates.

modelBuilder.Entity<Employee>()
    .Property(b => b.LastPayRaise)
    .ValueGeneratedOnAddOrUpdate();

modelBuilder.Entity<Employee>()
    .Property(b => b.LastPayRaise)
    .Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;

Uwaga

Domyślnie program EF Core spowoduje zgłoszenie wyjątku, jeśli zostanie podjęta próba zapisania jawną wartość dla właściwości, który jest skonfigurowany do wygenerowania podczas aktualizacji.By default, EF Core will throw an exception if you try to save an explicit value for a property that is configured to be generated during update. Aby tego uniknąć, należy do listy rozwijanej na niższym poziomie metadanych interfejsu API i ustaw AfterSaveBehavior (jak pokazano powyżej).To avoid this, you need to drop down to the lower level metadata API and set the AfterSaveBehavior (as shown above).

Uwaga

Zmiany w programie EF Core 2.0: w poprzednich wersjach zachowanie wtórnym Zapisz został kontrolowane za pośrednictwem IsReadOnlyAfterSave flagi.Changes in EF Core 2.0: In previous releases the after-save behavior was controlled through the IsReadOnlyAfterSave flag. Ta flaga został zamieniono przestarzały parametr i zastąpione przez AfterSaveBehavior.This flag has been obsoleted and replaced by AfterSaveBehavior.

Istnieje również wyzwalacza w bazie danych do generowania wartości dla LastPayRaise kolumny podczas UPDATE operacji.There is also a trigger in the database to generate values for the LastPayRaise column during UPDATE operations.

CREATE TRIGGER [dbo].[Employees_UPDATE] ON [dbo].[Employees]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;
                  
    IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
                  
    IF UPDATE(Salary) AND NOT Update(LastPayRaise)
    BEGIN
        DECLARE @Id INT
        DECLARE @OldSalary INT
        DECLARE @NewSalary INT
          
        SELECT @Id = INSERTED.EmployeeId, @NewSalary = Salary        
        FROM INSERTED
          
        SELECT @OldSalary = Salary        
        FROM deleted
          
        IF @NewSalary > @OldSalary
        BEGIN
            UPDATE dbo.Employees
            SET LastPayRaise = CONVERT(date, GETDATE())
            WHERE EmployeeId = @Id
        END
    END
END

Poniższy kod powoduje zwiększenie wynagrodzenia dwóch pracowników w bazie danych.The following code increases the salary of two employees in the database.

  • W pierwszym, zostanie przypisana żadna wartość, aby Employee.LastPayRaise właściwości, dzięki czemu pozostanie ustawiony na wartość null.For the first, no value is assigned to Employee.LastPayRaise property, so it remains set to null.
  • Dla drugiego firma Microsoft ustawiono jawną wartość jeden tydzień temu (podniesienie płatność sięga wstecz).For the second, we have set an explicit value of one week ago (back dating the pay raise).
using (var context = new EmployeeContext())
{
    var john = context.Employees.Single(e => e.Name == "John Doe");
    john.Salary = 200;

    var jane = context.Employees.Single(e => e.Name == "Jane Doe");
    jane.Salary = 200;
    jane.LastPayRaise = DateTime.Today.AddDays(-7);

    context.SaveChanges();

    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name + ", " + employee.LastPayRaise);
    }
}

Dane wyjściowe pokazują, że bazy danych wygenerowaną wartość dla pierwszego pracownika i użyto naszych jawną wartość dla drugiego.Output shows that the database generated a value for the first employee and our explicit value was used for the second.

1: John Doe, 1/26/2017 12:00:00 AM
2: Jane Doe, 1/19/2017 12:00:00 AM