Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

ईएफ कोर 2.1 और पोमेलो का उपयोग करके क्रिएटऑन और अपडेटऑन कैसे बनाएं?

समस्या:

मैंने इसे पोमेलो में एक बग (जो प्रतीत होता है) तक सीमित कर दिया है। समस्या यहाँ है:

https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/issues /801

मुद्दा यह है कि पोमेलो एक defaultValue बनाता है DateTime . के लिए संपत्ति और माइग्रेशन उत्पन्न करते समय अन्य संरचनाएं। यदि माइग्रेशन पर एक डिफ़ॉल्ट मान सेट किया गया है, तो यह मूल्य निर्माण रणनीति को ओवरराइड करता है, और SQL तब गलत दिखता है।

समाधान माइग्रेशन जनरेट करना है, और फिर defaultValue . सेट करने के लिए माइग्रेशन फ़ाइल को मैन्युअल रूप से संशोधित करना है करने के लिए null (या पूरी लाइन हटा दें)।

उदाहरण के लिए, इसे बदलें:

migrationBuilder.AddColumn<DateTime>(
                name: "UpdatedTime",
                table: "SomeTable",
                nullable: false,
                defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)))
                .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn);

इसके लिए:

migrationBuilder.AddColumn<DateTime>(
                name: "UpdatedTime",
                table: "SomeTable",
                nullable: false)
                .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn);

तब माइग्रेशन स्क्रिप्ट DEFAULT CURRENT_TIMESTAMP के साथ सही SQL को थूक देगी TIMESTAMP . के लिए . अगर आप [Column(TypeName = "TIMESTAMP")] . को हटाते हैं विशेषता, यह एक datetime(6) . का उपयोग करेगा कॉलम और थूक दें DEFAULT CURRENT_TIMESTAMP(6)

समाधान:

मैं एक वर्कअराउंड के साथ आया हूं जो क्रिएटेड टाइम (डेटाबेस द्वारा केवल INSERT पर अपडेट किया गया) और अपडेटेड टाइम (डेटाबेस द्वारा केवल INSERT और UPDATE पर अपडेट किया गया) को सही ढंग से लागू करता है।

सबसे पहले, अपनी इकाई को इस प्रकार परिभाषित करें:

public class SomeEntity
{
    // Other properties here ...

    public DateTime CreatedTime { get; set; }
    public DateTime UpdatedTime { get; set; }
}

फिर, निम्नलिखित को OnModelCreating() में जोड़ें :

protected override void OnModelCreating(ModelBuilder builder)
{
    // Other model creating stuff here ...

    builder.Entity<SomeEntity>.Property(d => d.CreatedTime).ValueGeneratedOnAdd();
    builder.Entity<SomeEntity>.Property(d => d.UpdatedTime).ValueGeneratedOnAddOrUpdate();

    builder.Entity<SomeEntity>.Property(d => d.CreatedTime).Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
    builder.Entity<SomeEntity>.Property(d => d.CreatedTime).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
    builder.Entity<SomeEntity>.Property(d => d.UpdatedTime).Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
    builder.Entity<SomeEntity>.Property(d => d.UpdatedTime).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
}

यह एक आदर्श प्रारंभिक माइग्रेशन उत्पन्न करता है (जहां migrationBuilder.CreateTable प्रयोग किया जाता है), और अपेक्षित SQL उत्पन्न करता है:

`created_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
`updated_time` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),

यह चाहिए माइग्रेशन पर भी काम करते हैं जो मौजूदा तालिकाओं को अपडेट करते हैं, लेकिन सुनिश्चित करें कि defaultValue हमेशा शून्य होता है।

SetBeforeSaveBehavior और SetAfterSaveBehavior लाइनें EF को कभी भी बनाए गए समय को डिफ़ॉल्ट मान के साथ अधिलेखित करने का प्रयास करने से रोकती हैं। यह प्रभावी रूप से बनाए गए और अपडेट किए गए कॉलम को केवल ईएफ के दृष्टिकोण से पढ़ने के लिए बनाता है, जिससे डेटाबेस को सभी काम करने की इजाजत मिलती है।

आप इसे एक इंटरफ़ेस और एक्सटेंशन विधि में भी निकाल सकते हैं:

public interface ITimestampedEntity
    {
        DateTime CreatedTime { get; set; }
        DateTime UpdatedTime { get; set; }
    }
public static EntityTypeBuilder<TEntity> UseTimestampedProperty<TEntity>(this EntityTypeBuilder<TEntity> entity) where TEntity : class, ITimestampedEntity
{
    entity.Property(d => d.CreatedTime).ValueGeneratedOnAdd();
    entity.Property(d => d.UpdatedTime).ValueGeneratedOnAddOrUpdate();

    entity.Property(d => d.CreatedTime).SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
    entity.Property(d => d.CreatedTime).SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
    entity.Property(d => d.UpdatedTime).SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
    entity.Property(d => d.UpdatedTime).SetAfterSaveBehavior(PropertySaveBehavior.Ignore);

    return entity;
}

फिर इंटरफ़ेस को अपनी सभी टाइमस्टैम्प वाली इकाइयों पर लागू करें:

public class SomeEntity : ITimestampedEntity
{
    // Other properties here ...

    public DateTime CreatedTime { get; set; }
    public DateTime UpdatedTime { get; set; }
}

यह आपको OnModelCreating() . के भीतर से इकाई को सेट करने की अनुमति देता है इस तरह:

protected override void OnModelCreating(ModelBuilder builder)
{
    // Other model creating stuff here ...

    builder.Entity<SomeTimestampedEntity>().UseTimestampedProperty();
}



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PDOException "ड्राइवर नहीं मिल सका"

  2. अधिकतम (समय) द्वारा समूह mysql

  3. NetBeans का उपयोग करके एक MySQL डेटाबेस का बैकअप और पुनर्स्थापना कैसे करें?

  4. अल्पविराम से अलग किये गए मान

  5. प्राथमिक में तालिका के विभाजन स्थान त्रुटि में सभी कॉलम शामिल होने चाहिए?