belirli bir özelliğe varsayılan değer vermenin "zarif" yolu var mı?
Belki de DataAnnotations ile:
[DefaultValue("true")]
public bool Active { get; set; }
Teşekkür ederim.
public bool Inactive { get; set; }
😉
belirli bir özelliğe varsayılan değer vermenin "zarif" yolu var mı?
Belki de DataAnnotations ile:
[DefaultValue("true")]
public bool Active { get; set; }
Teşekkür ederim.
public bool Inactive { get; set; }
😉
Yanıtlar:
İlk kod geçişini elle düzenleyerek yapabilirsiniz:
public override void Up()
{
AddColumn("dbo.Events", "Active", c => c.Boolean(nullable: false, defaultValue: true));
}
Active
için true
bir oluştururken Event
nesneyi de. Varsayılan değer her zaman false
nullable olmayan bir bool özelliğinde olur, bu nedenle değiştirilmedikçe varlık çerçevesi db'ye kaydedilecek olan budur. Yoksa bir şey mi kaçırıyorum?
Bir süre oldu, ama diğerleri için bir not bıraktı. Bir özellik ile ihtiyaç duyulanları elde ettim ve model sınıfı alanlarımı bu özellik ile istediğim gibi dekore ettim.
[SqlDefaultValue(DefaultValue = "getutcdate()")]
public DateTime CreatedDateUtc { get; set; }
Bu 2 makalenin yardımını aldım:
Ben ne yaptım:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class SqlDefaultValueAttribute : Attribute
{
public string DefaultValue { get; set; }
}
modelBuilder.Conventions.Add( new AttributeToColumnAnnotationConvention<SqlDefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.Single().DefaultValue));
private void SetAnnotatedColumn(ColumnModel col)
{
AnnotationValues values;
if (col.Annotations.TryGetValue("SqlDefaultValue", out values))
{
col.DefaultValueSql = (string)values.NewValue;
}
}
Daha sonra Geçiş Yapılandırması yapıcısında özel SQL üreticisini kaydedin.
SetSqlGenerator("System.Data.SqlClient", new CustomMigrationSqlGenerator());
[SqlDefaultValue(DefaultValue = "getutcdate()")]
her varlığı giymeden global olarak da yapabilirsiniz . 1) Basitçe kaldırın modelBuilder.Conventions.Add( new AttributeToColumnAnnotationConvention<SqlDefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.Single().DefaultValue));
2) EklemodelBuilder.Properties().Where(x => x.PropertyType == typeof(DateTime)).Configure(c => c.HasColumnType("datetime2").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed).HasColumnAnnotation("SqlDefaultValue", "getdate()"));
Yukarıdaki cevaplar gerçekten yardımcı oldu, ancak çözümün sadece bir kısmını verdi. En büyük sorun, Varsayılan değer özniteliğini kaldırır kaldırmaz, veritabanındaki sütundaki kısıtlamanın kaldırılmamasıdır. Dolayısıyla, önceki varsayılan değer veritabanında kalmaya devam eder.
İşte öznitelik kaldırma SQL kısıtlamalarını kaldırma da dahil olmak üzere, sorunun tam bir çözüm. Ayrıca .NET Framework'ün yerel DefaultValue
özniteliğini yeniden kullanıyorum .
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[DefaultValue("getutcdate()")]
public DateTime CreatedOn { get; set; }
Bunun çalışması için IdentityModels.cs ve Configuration.cs dosyalarını güncellemeniz gerekir
ApplicationDbContext
Sınıfınıza bu yöntemi ekleyin / güncelleyin
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var convention = new AttributeToColumnAnnotationConvention<DefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.SingleOrDefault().Value.ToString());
modelBuilder.Conventions.Add(convention);
}
Configuration
Sınıf yapıcısını aşağıdaki gibi özel Sql üretecini kaydederek güncelleyin :
internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
// DefaultValue Sql Generator
SetSqlGenerator("System.Data.SqlClient", new DefaultValueSqlServerMigrationSqlGenerator());
}
}
Ardından, özel Sql üreteci sınıfını ekleyin (bunu Configuration.cs dosyasına veya ayrı bir dosyaya ekleyebilirsiniz )
internal class DefaultValueSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
private int dropConstraintCount = 0;
protected override void Generate(AddColumnOperation addColumnOperation)
{
SetAnnotatedColumn(addColumnOperation.Column, addColumnOperation.Table);
base.Generate(addColumnOperation);
}
protected override void Generate(AlterColumnOperation alterColumnOperation)
{
SetAnnotatedColumn(alterColumnOperation.Column, alterColumnOperation.Table);
base.Generate(alterColumnOperation);
}
protected override void Generate(CreateTableOperation createTableOperation)
{
SetAnnotatedColumns(createTableOperation.Columns, createTableOperation.Name);
base.Generate(createTableOperation);
}
protected override void Generate(AlterTableOperation alterTableOperation)
{
SetAnnotatedColumns(alterTableOperation.Columns, alterTableOperation.Name);
base.Generate(alterTableOperation);
}
private void SetAnnotatedColumn(ColumnModel column, string tableName)
{
AnnotationValues values;
if (column.Annotations.TryGetValue("SqlDefaultValue", out values))
{
if (values.NewValue == null)
{
column.DefaultValueSql = null;
using (var writer = Writer())
{
// Drop Constraint
writer.WriteLine(GetSqlDropConstraintQuery(tableName, column.Name));
Statement(writer);
}
}
else
{
column.DefaultValueSql = (string)values.NewValue;
}
}
}
private void SetAnnotatedColumns(IEnumerable<ColumnModel> columns, string tableName)
{
foreach (var column in columns)
{
SetAnnotatedColumn(column, tableName);
}
}
private string GetSqlDropConstraintQuery(string tableName, string columnName)
{
var tableNameSplittedByDot = tableName.Split('.');
var tableSchema = tableNameSplittedByDot[0];
var tablePureName = tableNameSplittedByDot[1];
var str = $@"DECLARE @var{dropConstraintCount} nvarchar(128)
SELECT @var{dropConstraintCount} = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'{tableSchema}.[{tablePureName}]')
AND col_name(parent_object_id, parent_column_id) = '{columnName}';
IF @var{dropConstraintCount} IS NOT NULL
EXECUTE('ALTER TABLE {tableSchema}.[{tablePureName}] DROP CONSTRAINT [' + @var{dropConstraintCount} + ']')";
dropConstraintCount = dropConstraintCount + 1;
return str;
}
}
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Özelliğin ayarlanmasına ihtiyacım var mı? Öyleyse neden? Testlerimde, bunu dışarıda bırakmanın bir etkisi yok gibi görünüyordu.
Daha kolay olmasına rağmen model özelliklerinizin 'otomatik özellikler' olması gerekmez. Ve DefaultValue özniteliği gerçekten sadece bilgilendirici meta verilerdir. Burada kabul edilen cevap , yapıcı yaklaşımına bir alternatiftir.
public class Track
{
private const int DEFAULT_LENGTH = 400;
private int _length = DEFAULT_LENGTH;
[DefaultValue(DEFAULT_LENGTH)]
public int LengthInMeters {
get { return _length; }
set { _length = value; }
}
}
vs.
public class Track
{
public Track()
{
LengthInMeters = 400;
}
public int LengthInMeters { get; set; }
}
Bu yalnızca bu sınıfı kullanarak veri oluşturan ve tüketen uygulamalar için geçerlidir. Veri erişim kodu merkezileştirilmişse genellikle bu bir sorun oluşturmaz. Değeri tüm uygulamalarda güncellemek için veri kaynağını varsayılan bir değer ayarlayacak şekilde yapılandırmanız gerekir. Devi'nin cevabı , taşıma işlemleri, sql veya veri kaynağınızın konuştuğu her dil kullanılarak nasıl yapılabileceğini gösterir.
Ne yaptım, varlığın kurucusundaki değerleri başlattım
Not: DefaultValue özellikleri, özelliklerinizin değerlerini otomatik olarak ayarlamaz, bunu kendiniz yapmanız gerekir
@SedatKapanoglu yorumundan sonra, işe yarayan tüm yaklaşımımı ekliyorum, çünkü haklıydı, sadece akıcı API'yi kullanmak işe yaramıyor.
1- Özel kod oluşturucu oluşturun ve bir ColumnModel için üret seçeneğini geçersiz kılın.
public class ExtendedMigrationCodeGenerator : CSharpMigrationCodeGenerator
{
protected override void Generate(ColumnModel column, IndentedTextWriter writer, bool emitName = false)
{
if (column.Annotations.Keys.Contains("Default"))
{
var value = Convert.ChangeType(column.Annotations["Default"].NewValue, column.ClrDefaultValue.GetType());
column.DefaultValue = value;
}
base.Generate(column, writer, emitName);
}
}
2- Yeni kod oluşturucuyu atayın:
public sealed class Configuration : DbMigrationsConfiguration<Data.Context.EfSqlDbContext>
{
public Configuration()
{
CodeGenerator = new ExtendedMigrationCodeGenerator();
AutomaticMigrationsEnabled = false;
}
}
3- Ek Açıklama oluşturmak için akıcı api kullanın:
public static void Configure(DbModelBuilder builder){
builder.Entity<Company>().Property(c => c.Status).HasColumnAnnotation("Default", 0);
}
Basit! Sadece ek açıklama ekleyin.
[Required]
public bool MyField { get; set; }
sonuçta ortaya çıkan göç:
migrationBuilder.AddColumn<bool>(
name: "MyField",
table: "MyTable",
nullable: false,
defaultValue: false);
Doğru istiyorsanız, veritabanını güncellemeden önce geçişte defaultValue değerini true olarak değiştirin
true
?
Yaklaşımımın "İlk Kod" kavramından kaçtığını itiraf ediyorum. Ancak, tablonun kendisinde sadece varsayılan değeri değiştirme yeteneğine sahipseniz ... yukarıda geçmeniz gereken uzunluklardan çok daha basit ... Tüm bu işleri yapmak için çok tembelim!
Neredeyse posterlerin orijinal fikri işe yarayacak gibi görünüyor:
[DefaultValue(true)]
public bool IsAdmin { get; set; }
Ben sadece tırnak ekleme hatası yaptığını düşündüm ... ama ne yazık ki böyle bir sezgisellik yok. Diğer öneriler benim için çok fazlaydı (tabloya girip değişiklikleri yapmak için gerekli ayrıcalıklara sahip olduğumu kabul ettim. Sonunda sadece eski moda bir şekilde yaptım. SQL Server tablosunda varsayılan değeri ayarladım ... Yani, zaten yeterli! Not: Ayrıca bir ekleme-taşıma ve güncelleştirme-veritabanı yaparken test ve değişiklikler sıkışmış.
Sadece Model sınıfının varsayılan yapıcısını aşırı yükleyin ve kullanabileceğiniz veya kullanamayacağınız herhangi bir ilgili parametreyi geçirin. Bu şekilde, öznitelikler için kolayca varsayılan değerleri sağlayabilirsiniz. Aşağıda bir örnek verilmiştir.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Aim.Data.Domain
{
[MetadataType(typeof(LoginModel))]
public partial class Login
{
public Login(bool status)
{
this.CreatedDate = DateTime.Now;
this.ModifiedDate = DateTime.Now;
this.Culture = "EN-US";
this.IsDefaultPassword = status;
this.IsActive = status;
this.LoginLogs = new HashSet<LoginLog>();
this.LoginLogHistories = new HashSet<LoginLogHistory>();
}
}
public class LoginModel
{
[Key]
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required]
public string LoginCode { get; set; }
[Required]
public string Password { get; set; }
public string LastPassword { get; set; }
public int UserGroupId { get; set; }
public int FalseAttempt { get; set; }
public bool IsLocked { get; set; }
public int CreatedBy { get; set; }
public System.DateTime CreatedDate { get; set; }
public Nullable<int> ModifiedBy { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
public string Culture { get; set; }
public virtual ICollection<LoginLog> LoginLogs { get; set; }
public virtual ICollection<LoginLogHistory> LoginLogHistories { get; set; }
}
}
Ürünler adında bir sınıf adınız ve bir IsActive alanınız olduğunu varsayalım. sadece bir oluşturucu oluşturmalısınız:
Public class Products
{
public Products()
{
IsActive = true;
}
public string Field1 { get; set; }
public string Field2 { get; set; }
public bool IsActive { get; set; }
}
O zaman IsActive varsayılan değeriniz True!
Edite :
SQL ile bunu yapmak istiyorsanız şu komutu kullanın:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.IsActive)
.HasDefaultValueSql("true");
}
27 Haziran 2016'da yayınlanan EF çekirdeğinde, varsayılan değeri ayarlamak için akıcı API kullanabilirsiniz. ApplicationDbContext sınıfına gidin, OnModelCreating yöntem adını bulun / oluşturun ve aşağıdaki akıcı API'yi ekleyin.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<YourTableName>()
.Property(b => b.Active)
.HasDefaultValue(true);
}
.NET Core 3.1'de model sınıfında aşağıdakileri yapabilirsiniz:
public bool? Active { get; set; }
DbContext OnModelCreating'de varsayılan değeri eklersiniz.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Foundation>()
.Property(b => b.Active)
.HasDefaultValueSql("1");
base.OnModelCreating(modelBuilder);
}
Sonuçta aşağıdaki veritabanında
Not: Mülkünüz için boş değer (bool?) Yoksa aşağıdaki uyarıyı alırsınız
The 'bool' property 'Active' on entity type 'Foundation' is configured with a database-generated default. This default will always be used for inserts when the property has the value 'false', since this is the CLR default for the 'bool' type. Consider using the nullable 'bool?' type instead so that the default will only be used for inserts when the property value is 'null'.
Ben varlık özelliği sadece Auto-Property Initializer kullanarak işi yapmak için yeterli olduğunu buldum.
Örneğin:
public class Thing {
public bool IsBigThing{ get; set; } = false;
}
Hmm ... Önce DB yapıyorum ve bu durumda, bu aslında çok daha kolay. EF6 değil mi? Sadece modelinizi açın, varsayılanı ayarlamak istediğiniz sütuna sağ tıklayın, özellikleri seçin ve bir "DefaultValue" alanı göreceksiniz. Sadece doldurun ve kaydedin. Kodu sizin için ayarlayacaktır.
Kilometre kodunuz ilk önce değişebilir, ancak bununla çalışmadım.
Diğer birçok çözümle ilgili sorun, başlangıçta çalışabilirken, modeli yeniden oluşturduğunuzda, makine tarafından oluşturulan dosyaya eklediğiniz herhangi bir özel kodu atayacağıdır.
Bu yöntem, edmx dosyasına ekstra bir özellik ekleyerek çalışır:
<EntityType Name="Thingy">
<Property Name="Iteration" Type="Int32" Nullable="false" **DefaultValue="1"** />
Ve kurucuya gerekli kodu ekleyerek:
public Thingy()
{
this.Iteration = 1;
MSSQL Server'daki tabloda ve sınıf kodu add özniteliğinde sütun için varsayılan değeri şu şekilde ayarlayın:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
aynı mülk için.
this.Active = true;
? Ben getirilirken DB değeri öncelikli olacaktır düşünüyorum, ama dikkatli değişiklik izleme gibi bir getirme ilk olmadan bir güncelleme bir varlık takılarak sonra new'ing eğer olabilir Eğer değerini güncellemek isteyen olarak görüyoruz. Yorum yap, çünkü EF'i uzun zamandır kullanmadım ve bunun karanlıkta bir çekim olduğunu hissediyorum.