क्या विशिष्ट संपत्ति को डिफ़ॉल्ट मान देने का "सुरुचिपूर्ण" तरीका है?
शायद DataAnnotations द्वारा, कुछ इस तरह:
[DefaultValue("true")]
public bool Active { get; set; }
धन्यवाद।
public bool Inactive { get; set; }
H
क्या विशिष्ट संपत्ति को डिफ़ॉल्ट मान देने का "सुरुचिपूर्ण" तरीका है?
शायद DataAnnotations द्वारा, कुछ इस तरह:
[DefaultValue("true")]
public bool Active { get; set; }
धन्यवाद।
public bool Inactive { get; set; }
H
जवाबों:
आप इसे मैन्युअल रूप से कोड पहले प्रवास को संपादित करके कर सकते हैं:
public override void Up()
{
AddColumn("dbo.Events", "Active", c => c.Boolean(nullable: false, defaultValue: true));
}
Active
है true
जब कोई Event
ऑब्जेक्ट बना रहा है । डिफ़ॉल्ट मान हमेशा false
एक अशक्त बूल संपत्ति पर होता है, इसलिए जब तक इसे नहीं बदला जाता है, यह वह है जो इकाई रूपरेखा db में बचाएगा। या क्या मैं कुछ न कुछ भूल रहा हूं?
यह कुछ समय के लिए है, लेकिन दूसरों के लिए एक नोट छोड़ रहा है। मैंने वह हासिल किया है जो एक विशेषता के साथ आवश्यक है और मैंने अपने मॉडल वर्ग के क्षेत्रों को उस विशेषता के साथ सजाया है जैसा मैं चाहता हूं।
[SqlDefaultValue(DefaultValue = "getutcdate()")]
public DateTime CreatedDateUtc { get; set; }
इन 2 लेखों की मदद ली:
मैंने क्या किया:
[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;
}
}
फिर माइग्रेशन कॉन्फ़िगरेशन कंस्ट्रक्टर में, कस्टम SQL जनरेटर रजिस्टर करें।
SetSqlGenerator("System.Data.SqlClient", new CustomMigrationSqlGenerator());
[SqlDefaultValue(DefaultValue = "getutcdate()")]
हर संस्था पर लगाए बिना भी विश्व स्तर पर कर सकते हैं । 1) modelBuilder.Conventions.Add( new AttributeToColumnAnnotationConvention<SqlDefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.Single().DefaultValue));
modelBuilder.Properties().Where(x => x.PropertyType == typeof(DateTime)).Configure(c => c.HasColumnType("datetime2").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed).HasColumnAnnotation("SqlDefaultValue", "getdate()"));
उपरोक्त उत्तर वास्तव में मदद करते हैं, लेकिन केवल समाधान का हिस्सा दिया जाता है। प्रमुख मुद्दा यह है कि जैसे ही आप डिफ़ॉल्ट मान विशेषता को हटाते हैं, डेटाबेस में कॉलम पर बाधा को हटाया नहीं जाएगा। पिछले डिफ़ॉल्ट मान अभी भी डेटाबेस में रहेगा।
यहाँ समस्या का एक पूर्ण समाधान है, जिसमें विशेषता हटाने पर SQL बाधाओं को हटाना शामिल है। मैं .NET फ्रेमवर्क की मूल DefaultValue
विशेषता का भी पुन: उपयोग कर रहा हूं ।
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[DefaultValue("getutcdate()")]
public DateTime CreatedOn { get; set; }
इसके लिए आपको IdentityModels.cs और configuration.cs फ़ाइलों को अपडेट करने की आवश्यकता है
इस विधि को अपनी ApplicationDbContext
कक्षा में जोड़ें / अपडेट करें
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
कस्टम वर्ग जनरेटर को पंजीकृत करके अपने वर्ग निर्माता को अपडेट करें , जैसे:
internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
// DefaultValue Sql Generator
SetSqlGenerator("System.Data.SqlClient", new DefaultValueSqlServerMigrationSqlGenerator());
}
}
इसके बाद, कस्टम Sql जनरेटर वर्ग जोड़ें (आप इसे configuration.cs फ़ाइल या एक अलग फ़ाइल में जोड़ सकते हैं )
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)]
विशेषता चाहिए? यदि हां, तो क्यों? मेरे परीक्षणों में इसे छोड़ने का कोई प्रभाव नहीं था।
आपके मॉडल के गुणों को 'ऑटो गुण' होना जरूरी नहीं है, हालांकि यह आसान है। और DefaultValue विशेषता वास्तव में केवल जानकारीपूर्ण मेटाडेटा है। यहां स्वीकार किया गया उत्तर कंस्ट्रक्टर दृष्टिकोण का एक विकल्प है।
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; }
}
}
बनाम
public class Track
{
public Track()
{
LengthInMeters = 400;
}
public int LengthInMeters { get; set; }
}
यह केवल इस विशिष्ट वर्ग का उपयोग करके डेटा बनाने और उपभोग करने वाले अनुप्रयोगों के लिए काम करेगा। यदि डेटा एक्सेस कोड केंद्रीकृत है तो आमतौर पर यह कोई समस्या नहीं है। सभी अनुप्रयोगों में मूल्य को अपडेट करने के लिए आपको डिफ़ॉल्ट मान सेट करने के लिए डेटा स्रोत कॉन्फ़िगर करना होगा। देवी का उत्तर बताता है कि यह कैसे किया जा सकता है जो माइग्रेशन, एसक्यूएल, या आपके डेटा स्रोत से जो भी भाषा बोलती है।
मैंने जो भी किया, मैंने इकाई के निर्माता में मूल्यों को इनिशियलाइज़ किया
नोट: DefaultValue विशेषताएँ आपके गुणों के मूल्यों को स्वचालित रूप से सेट नहीं करेंगी, आपको इसे स्वयं करना होगा
@SedatKapanoglu टिप्पणी के बाद, मैं अपने सभी दृष्टिकोण को जोड़ रहा हूं जो काम करता है, क्योंकि वह सही था, बस धाराप्रवाह एपीआई का उपयोग करने से काम नहीं होता है।
1- कस्टम कोड जनरेटर बनाएँ और एक ColumnModel के लिए उत्पन्न करें को ओवरराइड करें।
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- नए कोड जनरेटर को असाइन करें:
public sealed class Configuration : DbMigrationsConfiguration<Data.Context.EfSqlDbContext>
{
public Configuration()
{
CodeGenerator = new ExtendedMigrationCodeGenerator();
AutomaticMigrationsEnabled = false;
}
}
3- एनोटेशन बनाने के लिए धाराप्रवाह एपी का उपयोग करें:
public static void Configure(DbModelBuilder builder){
builder.Entity<Company>().Property(c => c.Status).HasColumnAnnotation("Default", 0);
}
यह आसान है! बस आवश्यकता के साथ एनोटेट करें।
[Required]
public bool MyField { get; set; }
परिणामी प्रवास होगा:
migrationBuilder.AddColumn<bool>(
name: "MyField",
table: "MyTable",
nullable: false,
defaultValue: false);
यदि आप सही चाहते हैं, तो डेटाबेस को अपडेट करने से पहले डिफ़ॉल्टवैल्यू को माइग्रेशन में सच में बदलें
true
?
मैं स्वीकार करता हूं कि मेरा दृष्टिकोण संपूर्ण "कोड फर्स्ट" अवधारणा से बच जाता है। लेकिन अगर आपके पास केवल तालिका में डिफ़ॉल्ट मान को बदलने की क्षमता है ... यह उन लंबाई की तुलना में बहुत सरल है जिन्हें आपको ऊपर से गुजरना पड़ता है ... मैं बस उस काम को करने के लिए बहुत आलसी हूं!
यह लगभग ऐसा लगता है जैसे कि पोस्टर मूल विचार काम करेगा:
[DefaultValue(true)]
public bool IsAdmin { get; set; }
मुझे लगा कि उन्होंने सिर्फ उद्धरण जोड़ने की गलती की है ... लेकिन अफसोस ऐसी कोई बात नहीं है। अन्य सुझाव मेरे लिए बहुत अधिक थे (मुझे दी गई जानकारी के लिए मेज पर जाने और बदलाव करने की आवश्यकता है ... जहां हर डेवलपर हर स्थिति में नहीं होगा)। अंत में मैंने बस इसे पुराने तरीके से किया। मैंने SQL सर्वर तालिका में डिफ़ॉल्ट मान सेट किया है ... मेरा मतलब है कि वास्तव में, पहले से ही पर्याप्त है! ध्यान दें: मैंने आगे एक ऐड-माइग्रेशन और अपडेट-डेटाबेस का परीक्षण किया और परिवर्तन अटक गए।
बस मॉडल क्लास के डिफॉल्ट कंस्ट्रक्टर को ओवरलोड करें और कोई भी प्रासंगिक पैरामीटर पास करें जो आप उपयोग कर सकते हैं या नहीं। इसके द्वारा आप आसानी से विशेषताओं के लिए डिफ़ॉल्ट मानों की आपूर्ति कर सकते हैं। नीचे एक उदाहरण है।
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; }
}
}
आइए विचार करें कि आपके पास उत्पाद नाम का एक वर्ग नाम है और आपके पास एक IsActive फ़ील्ड है। बस आपको एक निर्माणकर्ता की आवश्यकता है:
Public class Products
{
public Products()
{
IsActive = true;
}
public string Field1 { get; set; }
public string Field2 { get; set; }
public bool IsActive { get; set; }
}
तब आपका IsActive डिफ़ॉल्ट मान True होता है!
संपादन :
यदि आप SQL के साथ इस कमांड का उपयोग करना चाहते हैं:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.IsActive)
.HasDefaultValueSql("true");
}
27 जून 2016 को जारी ईएफ कोर में आप डिफॉल्ट वैल्यू सेट करने के लिए धाराप्रवाह एपीआई का उपयोग कर सकते हैं। ApplicationDbContext क्लास में जाएं, OnModelCreating विधि नाम खोजें / बनाएं और निम्न धाराप्रवाह एपीआई जोड़ें।
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<YourTableName>()
.Property(b => b.Active)
.HasDefaultValue(true);
}
.NET कोर 3.1 में आप मॉडल वर्ग में निम्नलिखित कर सकते हैं:
public bool? Active { get; set; }
DbContext OnModelCreating में आप डिफ़ॉल्ट मान जोड़ते हैं।
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Foundation>()
.Property(b => b.Active)
.HasDefaultValueSql("1");
base.OnModelCreating(modelBuilder);
}
डेटाबेस में निम्नलिखित में परिणाम
नोट: यदि आपके पास संपत्ति के लिए अशक्त (बूल?) नहीं है, तो आपको निम्नलिखित चेतावनी मिलेगी
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'.
मैंने पाया कि बस प्रॉपर्टी पर ऑटो-प्रॉपर्टी इनिशियलाइज़र का उपयोग करना काम पाने के लिए पर्याप्त है।
उदाहरण के लिए:
public class Thing {
public bool IsBigThing{ get; set; } = false;
}
हम्म ... मैं पहले डीबी करता हूं, और उस मामले में, यह वास्तव में बहुत आसान है। EF6 सही है? बस अपना मॉडल खोलें, उस कॉलम पर राइट क्लिक करें जिसके लिए आप डिफ़ॉल्ट सेट करना चाहते हैं, गुण चुनें, और आपको एक "डिफ़ॉल्ट" फ़ील्ड दिखाई देगा। बस उसे भरें और बचाएं। यह आपके लिए कोड सेट करेगा।
आपका माइलेज पहले कोड पर अलग-अलग हो सकता है, हालांकि मैंने उसके साथ काम नहीं किया है।
कई अन्य समाधानों के साथ समस्या यह है कि जब वे शुरू में काम कर सकते हैं, जैसे ही आप मॉडल का पुनर्निर्माण करते हैं, तो यह आपके द्वारा मशीन-जनरेटेड फ़ाइल में डाला गया कोई भी कस्टम कोड निकाल देगा।
यह विधि edmx फ़ाइल में एक अतिरिक्त गुण जोड़कर काम करती है:
<EntityType Name="Thingy">
<Property Name="Iteration" Type="Int32" Nullable="false" **DefaultValue="1"** />
और निर्माणकर्ता को आवश्यक कोड जोड़कर:
public Thingy()
{
this.Iteration = 1;
MSSQL सर्वर में तालिका में स्तंभ के लिए डिफ़ॉल्ट मान सेट करें, और वर्ग कोड में इस तरह से विशेषता जोड़ें:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
उसी संपत्ति के लिए।
this.Active = true;
? मुझे लगता है कि डी.बी. मूल्य प्राप्त करने के दौरान पूर्वता बरतेंगे, लेकिन सावधान रहें यदि new'ing तो पहले बिना किसी अपडेट के लिए एक इकाई संलग्न कर रहा है, क्योंकि परिवर्तन ट्रैकिंग आप मूल्य को अद्यतन करने के इच्छुक के रूप में देख सकते हैं। टिप्पणी करें क्योंकि मैंने लंबे समय में ईएफ का उपयोग नहीं किया है, और मुझे ऐसा लगता है कि यह अंधेरे में एक शॉट है।