সত্তা ফ্রেমওয়ার্ক স্থানান্তরগুলিতে প্রয়োজনীয় ক্ষেত্রগুলির জন্য ডিফল্ট মান?


92

আমি [Required]একটি এএসপি.নেট এমভিসি অ্যাপ্লিকেশনটিতে আমার মডেলগুলির একটিতে ডেটা টীকা যুক্ত করেছি । মাইগ্রেশন তৈরির পরে, Update-Databaseকমান্ডটি চালনা করলে নিম্নলিখিত ত্রুটির ফলাফল হয়:

মান 'নুল' কলামে 'পরিচালক', সারণী 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies' এ সন্নিবেশ করা যায় না; কলামটি নালার অনুমতি দেয় না। আপডেট ব্যর্থ। বিবৃতিতে বাতিল করা হয়েছে।

এটি কিছু রেকর্ডগুলির কারণে তাদের Directorকলামগুলিতে নুয়াল রয়েছে is আমি কীভাবে স্বয়ংক্রিয়ভাবে এই মানগুলিকে কিছু ডিফল্ট ("জন ডো" বলুন) পরিচালক হিসাবে পরিবর্তন করতে পারি?

এখানে আমার মডেল:

  public class Movie
    {
        public int ID { get; set; }
        [Required]
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Required]
        public string Genre { get; set; }

        [Range(1,100)]
        [DataType(DataType.Currency)]
        public decimal Price { get; set; }

        [StringLength(5)]
        public string Rating { get; set; }

        [Required]     /// <--- NEW
        public string Director { get; set; }
    }

এবং এখানে আমার সর্বশেষ স্থানান্তর:

public partial class AddDataAnnotationsMig : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false));
        AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false));
        AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
        AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false));
    }

    public override void Down()
    {
        AlterColumn("dbo.Movies", "Director", c => c.String());
        AlterColumn("dbo.Movies", "Rating", c => c.String());
        AlterColumn("dbo.Movies", "Genre", c => c.String());
        AlterColumn("dbo.Movies", "Title", c => c.String());
    }
}

উত্তর:


74

যদি আমি সঠিকভাবে মনে রাখি তবে এর মতো কিছু কাজ করা উচিত:

AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, defaultValueSql: "'John Doe'"));

দ্রষ্টব্য: ডিফল্টভ্যালিউএসকিউএল প্যারামিটার মানটিকে ভার্ব্যাটিম এসকিউএল স্টেটমেন্ট হিসাবে বিবেচনা করা হয়, সুতরাং প্রয়োজনীয় মানটি যদি জন ড উদাহরণের মতো কার্যকরভাবে একটি স্ট্রিং হয়, তবে মানটির চারপাশে একক উদ্ধৃতি প্রয়োজন।


9
আমিও তাই ভেবেছিলাম, তবে বিদ্যমান রেকর্ডগুলির জন্য এটি কাজ বলে মনে হচ্ছে না। সুতরাং আমি এখনও একটি ত্রুটি পেতে।
অ্যান্ড্রি দ্রোজডিয়ুক

@ডরোজি সম্ভবত এটি এখানে বাগের মতো: EF 4.3.1 মাইগ্রেশন ব্যতিক্রম - অ্যালটারকলাম ডিফল্টভ্যালু এসকিউএল বিভিন্ন সারণীর জন্য একই ডিফল্ট সীমাবদ্ধতার নাম তৈরি করে আপনি IS NULLআপনার ক্যোয়ারী অনুসারে চেক দিয়ে সারিগুলি আপডেট করতে পারেন ।
ওয়েবডিপোপার

আকর্ষণীয়, তবে আমি নিশ্চিত নই যে তারা কী বলছে I তবে এটি যদি কোনও বাগ হয় তবে হ্যাঁ, এটি বোঝা যাবে।
অ্যান্ড্রি দ্রোজডিয়ুক

6
আমি মনে করি এটি হওয়া উচিত: "'John Doe'"- আপনার এসকিউএল কোট ব্যবহার করা উচিত ।
শান 13

4
@ ওয়েবে ডেভেলপার, আমি মনে করি না এটি একটি বাগ, কেন AlterColumnবর্তমান মানগুলি আপডেট করবে ? এটি একটি ডিডিএল (ডিএমএল নয়) কমান্ড।
অ্যান্টন

110

@ ওয়েবেডাবলাপার এবং @ পুশপেন্দ্রের উত্তর ছাড়াও, বিদ্যমান সারিগুলি আপডেট করার জন্য আপনাকে নিজের মাইগ্রেশনে ম্যানুয়ালি আপডেট যুক্ত করতে হবে। উদাহরণ স্বরূপ:

public override void Up()
{
    Sql("UPDATE [dbo].[Movies] SET Title = 'No Title' WHERE Title IS NULL");
    AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle"));
}

এই কারণ AlterColumn টেবিলের স্পেসিফিকেশনে কিছু নির্দিষ্ট মান কলামের ডিফল্ট সেট করতে ডিডিএল উত্পাদন করে। ডিডিএল ডাটাবেজে বিদ্যমান সারিগুলিকে প্রভাবিত করে না।

আপনি একই সময়ে দুটি পরিবর্তন করছেন (ডিফল্ট সেট করা এবং কলামটি নাল নয়) এবং এগুলির প্রতিটি স্বতন্ত্রভাবে বৈধ, তবে যেহেতু আপনি একই সাথে দুটি তৈরি করছেন, আপনি সিস্টেমটি আশা করতে পারেন বুদ্ধিমানের সাথে আপনার উদ্দেশ্যটি উপলব্ধি করুন এবং সমস্ত NULLমানকে ডিফল্ট মানটিতে সেট করুন , তবে এটি সর্বদা প্রত্যাশিত নয়।

মনে করুন আপনি কলামটির জন্য কেবলমাত্র ডিফল্ট মান সেট করছেন, এবং এটি নকল করছেন না। আপনি অবশ্যই স্পষ্টভাবে আশা করেন না যে সমস্ত সরবরাহ করা NUL রেকর্ডার আপনার সরবরাহিত ডিফল্ট সাথে আপডেট হবে updated

সুতরাং, আমার মতে, এটি কোনও ত্রুটি নয় এবং আমি চাই না যে EF আমার উপাত্তগুলিকে সেইভাবে আপডেট করতে পারে যা আমি স্পষ্টভাবে এটি করতে বলি না। ডেটা দিয়ে কী করা উচিত সে সম্পর্কে সিস্টেমকে নির্দেশ দেওয়ার জন্য বিকাশকারী দায়বদ্ধ।


17
লোকেরা এই উত্তরটি গুগলের মাধ্যমে খুঁজে পেয়েছে: আমি এটি কেবল EF6-এ চেষ্টা করেছি এবং আপডেট বিবৃতিটি (আর দরকার নেই) বলে মনে হচ্ছে। আমার ধারণা তারা এটিকে একটি বাগ হিসাবে বিবেচনা করেছে।
EPLKleijntjens

4
আমি এটির জন্যও নিশ্চয়তা দিতে পারি। আপনার যদি কোনও অযোগ্য ক্ষেত্রের জন্য এমনকি ডিফল্ট মান প্রয়োজন হয় তবে এটির জন্য প্রথমে একটি ডিফল্ট মান দিয়ে প্রথমে নন-অ্যালবামে পরিবর্তন করুন এবং তারপরে এটিকে আবার পরিবর্তনযোগ্যতে পরিবর্তন করুন। যখন আপনি একটি শিশু শ্রেণিতে একটি অ-শর্তযুক্ত ক্ষেত্র যুক্ত করেছেন তখন খুব কার্যকর :)
ওয়াউটার শুট

4
ব্যাখ্যা স্পট। অল্টারক্লোনম () কেবল কলাম সংজ্ঞা পরিবর্তিত করে। এটি বিদ্যমান রেকর্ডগুলিকে
কোনওভাবেই

10
public partial class AddDataAnnotationsMig : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle"));
        AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false,defaultValue:"Genre"));
        AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
        AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false,defaultValue:"Director"));

    }

    public override void Down()
    {       
        AlterColumn("dbo.Movies", "Director", c => c.String());
        AlterColumn("dbo.Movies", "Rating", c => c.String());
        AlterColumn("dbo.Movies", "Genre", c => c.String());
        AlterColumn("dbo.Movies", "Title", c => c.String());       
    }
}

4
উম ... ধন্যবাদ, তবে এটি কীভাবে ওয়েব ওয়েব ডেভেলপারের উত্তর থেকে আলাদা?
অ্যান্ড্রি দ্রোজডিয়ুক

4
এটি আপনাকে জানায় না যে আপনাকে ডিফল্ট মান প্যারামিটারটি কোথায় যুক্ত করতে হবে
পুষ্পেন্দ্র

4
@ পুষ্পেন্দ্র, এটা মজার বিষয় যে বিকাশকারীরা একবারে ভুলে যাওয়ার ঝোঁক রাখেন যে তারা একবারে খুব বেশি কিছু জানত না। আমি বিস্তারিত উত্তরগুলি পছন্দ করি যা সমস্ত স্তরকে সন্তুষ্ট করে। চমৎকার কাজ!
দরকারী

5

নিশ্চিত না যে এই বিকল্পটি সবসময়ই ছিল তবে কেবল একই ধরণের ইস্যুতে ছড়িয়ে পড়েছে, আমি নিম্নলিখিতটি ব্যবহার করে কোনও ম্যানুয়াল আপডেট না চালিয়ে ডিফল্ট মান সেট করতে সক্ষম হয়েছি

defaultValueSql: "'NY'"

প্রদত্ত মানটি যখন "NY"তখন আমি একটি ত্রুটি পেয়েছি তখন বুঝতে পেরেছিলাম যে তারা এসকিউএল মানের মতো প্রত্যাশা করছে"GETDATE()" চেষ্টা করেছে"'NY'" এবং সেই কৌশলটি করেছে

পুরো লাইনটি দেখতে এমন দেখাচ্ছে

AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));

এই উত্তরটির জন্য ধন্যবাদ , আমাকে সঠিক পথে পৌঁছেছে


2

আমি দেখতে পেয়েছি যে সত্তা সম্পত্তিতে অটো-প্রপার্টি ইনিশিয়ালাইজার ব্যবহার করা কাজটি করার জন্য যথেষ্ট।

উদাহরণ স্বরূপ:

public class Thing {
    public bool IsBigThing { get; set; } = false;
}

4
এটি একটি ভাল উত্তর (আমাকে সাহায্য করেছে), কিন্তু এটি ডাটাবেসে কোনও ডিফল্ট মান যুক্ত করে না, এটি কোডে মান নির্ধারণ করে।
chris31389

ঠিক আছে এটি মাইগ্রেশন chnages পরে ডেটাবেস মধ্যে ডিফল্ট মান যোগ করেনি
চেতন

2

অন্যান্য প্রতিক্রিয়াগুলির মধ্যে অনেকগুলি এই সমস্যাগুলি দেখা দিলে কীভাবে ম্যানুয়ালি হস্তক্ষেপ করবেন সে সম্পর্কে ফোকাস দেয়।

মাইগ্রেশন জেনারেট করার পরে মাইগ্রেশনে নিম্নলিখিত যে কোনও পরিবর্তন সম্পাদন করুন:

  1. ডিফল্টভ্যালু বা ডিফল্ট এসকিএল বিবৃতি অন্তর্ভুক্ত করতে কলাম সংজ্ঞাটি সংশোধন করুন:
    AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, default: ""));

  2. অ্যালটারকালামের আগে বিদ্যমান কলামগুলি প্রাক-পূরণ করার জন্য একটি এসকিউএল স্টেটমেন্ট ইনজেক্ট করুন:
    Sql("UPDATE dbo.Movies SET Director = '' WHERE Director IS NULL");

মনে রাখবেন যে মাইগ্রেশন স্ক্রিপ্টে প্রয়োগ করা ম্যানুয়াল পরিবর্তনগুলি ওভাররাইট করা হবে যদি আপনি মাইগ্রেশনটিকে নতুন করে স্ক্যাফোড করেন। প্রথম সমাধানের জন্য, স্থানান্তর প্রজন্মের অংশ হিসাবে স্বয়ংক্রিয়ভাবে কোনও ক্ষেত্রে একটি ডিফল্ট মান নির্ধারণ করতে EF প্রসারিত করা বেশ সহজ pretty

দ্রষ্টব্য: EF স্বয়ংক্রিয়ভাবে আপনার জন্য এটি করে না কারণ প্রতিটি আরডিবিএমএস সরবরাহকারীর জন্য ডিফল্ট মান বাস্তবায়ন আলাদা হবে, তবে এটিও কারণ ডিফল্ট মানগুলি একটি খাঁটি EF রানটাইমটিতে কম অর্থ পায় কারণ প্রতিটি সারি সন্নিবেশ প্রতিটি সংস্থার বর্তমান মান প্রদান করবে, এমনকি যদি এটি বাতিল হয় তবে ডিফল্ট মান সীমাবদ্ধতা কখনই মূল্যায়ন হয় না।
এই অল্টারক্লাম বিবৃতিটি কেবলমাত্র যখন ডিফল্ট সীমাবদ্ধতাটি কার্যকর হয়, আমি অনুমান করি যে এটি এসকিউএল সার্ভার মাইগ্রেশন বাস্তবায়ন ডিজাইনকারী দলের জন্য একটি নিম্ন অগ্রাধিকার হয়ে উঠেছে।

নিম্নলিখিত সমাধানটিতে কাস্টম মাইগ্রেশন কোড জেনারেটরে মেটাডেটা দিয়ে যাওয়ার জন্য অ্যাট্রিবিউট নোটেশন, মডেল কনফিগারেশন কনভেনশন এবং কলাম টীকাগুলি একত্রিত করা হয়েছে। যদি আপনি অ্যাট্রিবিউট স্বরলিপিটি ব্যবহার না করে থাকেন তবে প্রতিটি প্রভাবিত ক্ষেত্রের জন্য 1 এবং 2 পদক্ষেপগুলি সাবলীল স্বরলিপি দ্বারা প্রতিস্থাপন করা যেতে পারে।
এখানে খেলতে প্রচুর কৌশল রয়েছে, কিছু না কিছু ব্যবহার করতে নির্দ্বিধায় থাকুন, আমি আশা করি যে এখানে সবার জন্য মূল্য রয়েছে


  1. ডিফল্ট মানটি ঘোষণা
    করুন ব্যবহারের জন্য ডিফল্ট মানটি সংজ্ঞায়িত করার জন্য একটি বিদ্যমান অ্যাট্রিবিউট তৈরি করুন বা পুনরায় উদ্দেশ্য করুন, উদাহরণস্বরূপ আমরা ডিফল্টভ্যালু নামে একটি নতুন অ্যাট্রিবিউট তৈরি করব যা কম্পোনেন্টমোডেল থেকে প্রাপ্ত হবে।ডাফল্টভ্যালুঅ্যাট্রিবিউট, কারণ ব্যবহারটি স্বজ্ঞাত এবং এটির সম্ভাবনা থাকার সম্ভাবনা রয়েছে কোড বেসগুলি ইতিমধ্যে এই বৈশিষ্ট্যটি প্রয়োগ করে। এই প্রয়োগের সাথে আপনাকে কেবল ডিফল্টভ্যালুএসকিউএল অ্যাক্সেস করতে এই নির্দিষ্ট বৈশিষ্ট্যটি ব্যবহার করতে হবে যা তারিখ এবং অন্যান্য কাস্টম দৃশ্যের জন্য দরকারী।

    বাস্তবায়ন

    [DefaultValue("Insert DefaultValue Here")]
    [Required]     /// <--- NEW
    public string Director { get; set; }
    
    // Example of default value sql
    [DefaultValue(DefaultValueSql: "GetDate()")]
    [Required]
    public string LastModified { get; set; }
    

    সংজ্ঞা সংজ্ঞা

    namespace EFExtensions
    {
        /// <summary>
        /// Specifies the default value for a property but allows a custom SQL statement to be provided as well. <see cref="MiniTuber.Database.Conventions.DefaultValueConvention"/>
        /// </summary>
        public class DefaultValueAttribute : System.ComponentModel.DefaultValueAttribute
        {
            /// <summary>
            /// Specifies the default value for a property but allows a custom SQL statement to be provided as well. <see cref="MiniTuber.Database.Conventions.DefaultValueConvention"/>
            /// </summary>
            public DefaultValueAttribute() : base("")
            {
            }
    
            /// <i
            /// <summary>
            /// Optional SQL to use to specify the default value.
            /// </summary>
            public string DefaultSql { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a Unicode character.
            /// </summary>
            /// <param name="value">
            /// A Unicode character that is the default value.
            /// </param>
            public DefaultValueAttribute(char value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using an 8-bit unsigned integer.
            /// </summary>
            /// <param name="value">
            /// An 8-bit unsigned integer that is the default value.
            /// </param>
            public DefaultValueAttribute(byte value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 16-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 16-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(short value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 32-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 32-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(int value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 64-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 64-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(long value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a single-precision floating point number.
            /// </summary>
            /// <param name="value">
            /// A single-precision floating point number that is the default value.
            /// </param>
            public DefaultValueAttribute(float value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a double-precision floating point number.
            /// </summary>
            /// <param name="value">
            /// A double-precision floating point number that is the default value.
            /// </param>
            public DefaultValueAttribute(double value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a System.Boolean value.
            /// </summary>
            /// <param name="value">
            /// A System.Boolean that is the default value.
            /// </param>
            public DefaultValueAttribute(bool value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a System.String.
            /// </summary>
            /// <param name="value">
            /// A System.String that is the default value.
            /// </param>
            public DefaultValueAttribute(string value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class.
            /// </summary>
            /// <param name="value">
            /// An System.Object that represents the default value.
            /// </param>
            public DefaultValueAttribute(object value) : base(value) { }
    
            /// /// <inheritdoc/>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class, converting the specified value to the specified type, and using an invariant
            /// culture as the translation context.
            /// </summary>
            /// <param name="type">
            /// A System.Type that represents the type to convert the value to.
            /// </param>
            /// <param name="value">
            /// A System.String that can be converted to the type using the System.ComponentModel.TypeConverter
            /// for the type and the U.S. English culture.
            /// </param>
            public DefaultValueAttribute(Type type, string value) : base(value) { }
        }
    }
    
  2. কলাম টীকাতে ডিফল্ট মান ইনজেকশনের জন্য একটি কনভেনশন তৈরি করুন কলামের টীকাগুলি
    মাইগ্রেশন স্ক্রিপ্ট জেনারেটরের মাধ্যমে কলামগুলি সম্পর্কে কাস্টম মেটাডেটা পাস করার জন্য ব্যবহৃত হয়।
    এটি করার জন্য একটি কনভেনশন ব্যবহার করে অবিচ্ছিন্ন মেটাডেটা প্রতিটি ক্ষেত্রের জন্য পৃথকভাবে উল্লেখ না করে কীভাবে অনেকগুলি সংখ্যার জন্য সংজ্ঞায়িত ও ম্যানিপুলেট করা যায় তা সহজ করার জন্য অ্যাট্রিবিউট নোটেশনের পিছনে শক্তি প্রদর্শন করে।

    namespace EFExtensions
    {
    
        /// <summary>
        /// Implement SQL Default Values from System.ComponentModel.DefaultValueAttribute
        /// </summary>
        public class DefaultValueConvention : Convention
        {
            /// <summary>
            /// Annotation Key to use for Default Values specified directly as an object
            /// </summary>
            public const string DirectValueAnnotationKey = "DefaultValue";
            /// <summary>
            /// Annotation Key to use for Default Values specified as SQL Strings
            /// </summary>
            public const string SqlValueAnnotationKey = "DefaultSql";
    
            /// <summary>
            /// Implement SQL Default Values from System.ComponentModel.DefaultValueAttribute
            /// </summary>
            public DefaultValueConvention()
            {
                // Implement SO Default Value Attributes first
                this.Properties()
                        .Where(x => x.HasAttribute<EFExtensions.DefaultValueAttribute>())
                        .Configure(c => c.HasColumnAnnotation(
                            c.GetAttribute<EFExtensions.DefaultValueAttribute>().GetDefaultValueAttributeKey(),
                            c.GetAttribute<EFExtensions.DefaultValueAttribute>().GetDefaultValueAttributeValue()
                            ));
    
                // Implement Component Model Default Value Attributes, but only if it is not the SO implementation
                this.Properties()
                        .Where(x => x.HasAttribute<System.ComponentModel.DefaultValueAttribute>())
                        .Where(x => !x.HasAttribute<MiniTuber.DataAnnotations.DefaultValueAttribute>())
                        .Configure(c => c.HasColumnAnnotation(
                            DefaultValueConvention.DirectValueAnnotationKey, 
                            c.GetAttribute<System.ComponentModel.DefaultValueAttribute>().Value
                            ));
            }
        }
    
        /// <summary>
        /// Extension Methods to simplify the logic for building column annotations for Default Value processing
        /// </summary>
        public static partial class PropertyInfoAttributeExtensions
        {
            /// <summary>
            /// Wrapper to simplify the lookup for a specific attribute on a property info.
            /// </summary>
            /// <typeparam name="T">Type of attribute to lookup</typeparam>
            /// <param name="self">PropertyInfo to inspect</param>
            /// <returns>True if an attribute of the requested type exists</returns>
            public static bool HasAttribute<T>(this PropertyInfo self) where T : Attribute
            {
                return self.GetCustomAttributes(false).OfType<T>().Any();
            }
    
            /// <summary>
            /// Wrapper to return the first attribute of the specified type
            /// </summary>
            /// <typeparam name="T">Type of attribute to return</typeparam>
            /// <param name="self">PropertyInfo to inspect</param>
            /// <returns>First attribuite that matches the requested type</returns>
            public static T GetAttribute<T>(this System.Data.Entity.ModelConfiguration.Configuration.ConventionPrimitivePropertyConfiguration self) where T : Attribute
            {
                return self.ClrPropertyInfo.GetCustomAttributes(false).OfType<T>().First();
            }
    
            /// <summary>
            /// Helper to select the correct DefaultValue annotation key based on the attribute values
            /// </summary>
            /// <param name="self"></param>
            /// <returns></returns>
            public static string GetDefaultValueAttributeKey(this EFExtensions.DefaultValueAttribute self)
            {
                return String.IsNullOrWhiteSpace(self.DefaultSql) ? DefaultValueConvention.DirectValueAnnotationKey : DefaultValueConvention.SqlValueAnnotationKey;
            }
    
            /// <summary>
            /// Helper to select the correct attribute property to send as a DefaultValue annotation value
            /// </summary>
            /// <param name="self"></param>
            /// <returns></returns>
            public static object GetDefaultValueAttributeValue(this EFExtensions.DefaultValueAttribute self)
            {
                return String.IsNullOrWhiteSpace(self.DefaultSql) ? self.Value : self.DefaultSql;
            }
        }
    
    }
    
  3. কনভেনশনটি ডিবি কনটেক্সটে যুক্ত করুন এটির আহরণের
    অনেকগুলি উপায় রয়েছে, আমি কনভেনশনগুলিকে আমার মডেলক্রিয়েশন যুক্তির প্রথম কাস্টম পদক্ষেপ হিসাবে ঘোষণা করতে চাই, এটি আপনার ডিবি কনটেক্সট ক্লাসে হবে।

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // Use our new DefaultValueConvention
        modelBuilder.Conventions.Add<EFExtensions.DefaultValueConvention>();
    
        // My personal favourites ;)
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    
    }
    

  4. মাইগ্রেশনকোড জেনারেটরকে ওভাররাইড করুন এখন those টিকাগুলি মডেলের মধ্যে কলাম সংজ্ঞাতে প্রয়োগ করা হয়েছে, সেই টীকাগুলি ব্যবহার করতে আমাদের মাইগ্রেশন স্ক্রিপ্ট জেনারেটরটি পরিবর্তন করতে হবে। এর জন্য আমরা উত্তরাধিকারী হব System.Data.Entity.Migrations.Design.CSharpMigrationCodeGeneratorকারণ আমাদের কেবলমাত্র একটি সংক্ষিপ্ত পরিমাণে পরিবর্তন ইনজেক্ট করতে হবে।
    একবার আমরা আমাদের কাস্টম টীকাটি প্রক্রিয়া করার পরে এটি চূড়ান্ত আউটপুটে সিরিয়ালায়িত হওয়া রোধ করার জন্য আমাদের এটি কলাম সংজ্ঞা থেকে অপসারণ করতে হবে।

    অন্যান্য ব্যবহারের অন্বেষণের জন্য বেস শ্রেণীর কোডটি দেখুন: http://entityframework.codeplex.com/sourcecontrol/latest#src/EntityFramework/Migrations/Design/CSharpMigrationCodeGenerator.cs

    namespace EFExtensions
    {
        /// <summary>
        /// Implement DefaultValue constraint definition in Migration Scripts.
        /// </summary>
        /// <remarks>
        /// Original guide that provided inspiration for this https://romiller.com/2012/11/30/code-first-migrations-customizing-scaffolded-code/
        /// </remarks>
        public class CustomCodeGenerator : System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
        {
            /// <summary>
            /// Inject Default values from the DefaultValue attribute, if the DefaultValueConvention has been enabled.
            /// </summary>
            /// <seealso cref="DefaultValueConvention"/>
            /// <param name="column"></param>
            /// <param name="writer"></param>
            /// <param name="emitName"></param>
            protected override void Generate(ColumnModel column, IndentedTextWriter writer, bool emitName = false)
            {
                var annotations = column.Annotations?.ToList();
                if (annotations != null && annotations.Any())
                {
                    for (int index = 0; index < annotations.Count; index ++)
                    {
                        var annotation = annotations[index];
                        bool handled = true;
    
                        try
                        {
                            switch (annotation.Key)
                            {
                                case DefaultValueConvention.SqlValueAnnotationKey:
                                    if (annotation.Value?.NewValue != null)
                                    {
                                        column.DefaultValueSql = $"{annotation.Value.NewValue}";
                                    }
                                    break;
                                case DefaultValueConvention.DirectValueAnnotationKey:
                                    if (annotation.Value?.NewValue != null)
                                    {
                                        column.DefaultValue = Convert.ChangeType(annotation.Value.NewValue, column.ClrType);
                                    }
                                    break;
                                default:
                                    handled = false;
                                    break;
                            }
                        }
                        catch(Exception ex)
                        {
                            // re-throw with specific debug information
                            throw new ApplicationException($"Failed to Implement Column Annotation for column: {column.Name} with key: {annotation.Key} and new value: {annotation.Value.NewValue}", ex);
                        }
    
                        if(handled)
                        {
                            // remove the annotation, it has been applied
                            column.Annotations.Remove(annotation.Key);
                        }
                    }
                }
                base.Generate(column, writer, emitName);
            }
    
            /// <summary>
            /// Generates class summary comments and default attributes
            /// </summary>
            /// <param name="writer"> Text writer to add the generated code to. </param>
            /// <param name="designer"> A value indicating if this class is being generated for a code-behind file. </param>
            protected override void WriteClassAttributes(IndentedTextWriter writer, bool designer)
            {
                writer.WriteLine("/// <summary>");
                writer.WriteLine("/// Definition of the Migration: {0}", this.ClassName);
                writer.WriteLine("/// </summary>");
                writer.WriteLine("/// <remarks>");
                writer.WriteLine("/// Generated Time: {0}", DateTime.Now);
                writer.WriteLine("/// Generated By: {0}", Environment.UserName);
                writer.WriteLine("/// </remarks>");
                base.WriteClassAttributes(writer, designer);
            }
    
    
        }
    }
    
  5. কাস্টোডজেইনরেটর নিবন্ধন করুন
    শেষ পদক্ষেপ, DbMigration কনফিগারেশন ফাইলে আমাদের কোড জেনারেটরটি ব্যবহার করার জন্য নির্দিষ্ট করতে হবে, আপনার মাইগ্রেশন ফোল্ডারে ডিফল্টরূপে কনফিগারেশন।

    internal sealed class Configuration : DbMigrationsConfiguration<YourApplication.Database.Context>
    {
        public Configuration()
        {
            // I recommend that auto-migrations be disabled so that we control
            // the migrations explicitly 
            AutomaticMigrationsEnabled = false;
            CodeGenerator = new EFExtensions.CustomCodeGenerator();
        }
    
        protected override void Seed(YourApplication.Database.Context context)
        {
            //   Your custom seed logic here
        }
    }
    

2

যেহেতু EF কোর ২.১, আপনি MigrationBuilder.UpdateDataকলাম পরিবর্তন করার আগে মানগুলি পরিবর্তন করতে ব্যবহার করতে পারেন (কাঁচা এসকিউএল ব্যবহারের চেয়ে পরিষ্কার):

protected override void Up(MigrationBuilder migrationBuilder)
{
    // Change existing NULL values to NOT NULL values
    migrationBuilder.UpdateData(
        table: tableName,
        column: columnName,
        value: valueInsteadOfNull,
        keyColumn: columnName,
        keyValue: null);

    // Change column type to NOT NULL
    migrationBuilder.AlterColumn<ColumnType>(
        table: tableName,
        name: columnName,
        nullable: false,
        oldClrType: typeof(ColumnType),
        oldNullable: true);
}

0

কোনও কারণে, আমি নিজেকে অনুমোদিত উত্তরটি ব্যাখ্যা করতে অক্ষম হয়েছি যে আমার পক্ষে আর কাজ করে না।

এটি অন্য একটি অ্যাপ্লিকেশনটিতে কাজ করেছে, আমি যেটিতে কাজ করছি তাতে এটি কার্যকর হয় না।

সুতরাং, একটি বিকল্প, তবে বেশ অদক্ষ , সমাধান হ'ল নমুনা হিসাবে সেভ চেঞ্জেস () পদ্ধতিটি ওভাররাইড করা হবে। এই পদ্ধতিটি প্রসঙ্গ শ্রেণিতে থাকা উচিত।

    public override int SaveChanges()
    {
        foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("ColumnName") != null))
        {
            if (entry.State == EntityState.Added)
            {
                entry.Property("ColumnName").CurrentValue = "DefaultValue";
            }
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.