EF কোড নেভিগেশন সম্পত্তি ছাড়াই প্রথম বিদেশী কী


91

ধরা যাক আমার নিম্নলিখিত সংস্থাগুলি রয়েছে:

public class Parent
{
    public int Id { get; set; }
}
public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }
}

কোনও নেভিগেশন সম্পত্তি না রেখে পিতামাতাদের টেবিলে বিদেশী কী বাধা দিয়ে ডেটাবেজে প্যারেন্টআইড তৈরি করা হয়েছে তা প্রয়োগ করার জন্য কোডটি প্রথম ফ্লুয়েন্ট এপিআই সিনট্যাক্স কী ?

আমি জানি যে আমি যদি একটি নেভিগেশন সম্পত্তি প্যারেন্ট অব চাইল্ডে যুক্ত করি তবে আমি এটি করতে পারি:

modelBuilder.Entity<Child>()
    .HasRequired<Parent>(c => c.Parent)
    .WithMany()
    .HasForeignKey(c => c.ParentId);

তবে আমি এই বিশেষ ক্ষেত্রে নেভিগেশন সম্পত্তি চাই না।


4
আমি মনে করি না এটি কেবলমাত্র EF- এর মাধ্যমে সম্ভব, আপনি সম্ভবত এটি সেট আপ করার জন্য ম্যানুয়াল মাইগ্রেশনে কিছু কাঁচা এসকিউএল ব্যবহার করতে হবে
পছন্দ নয়

@ লুকেমসিগ্রিগোর এটিই আমার ভয় ছিল। যদি আপনি এটির উত্তর দেন তবে আমি এটি গ্রহণ করে খুশি হব, ধরে নিলাম এটি সঠিক। :-)
যৌক্তিকগীত

নেভিগেশন সম্পত্তি না থাকার জন্য কোনও নির্দিষ্ট কারণ আছে? আপনার জন্য নেভিগেশন সম্পত্তি ব্যক্তিগত কাজ করা - সত্তার বাইরে দৃশ্যমান হবে না তবে EF খুশি হবে। (দ্রষ্টব্য আমি এটি চেষ্টা করি নি তবে আমি মনে করি এটি কাজ করা উচিত - ব্যক্তিগত সম্পত্তি romiller.com/2012/10/01/… ম্যাপিং সম্পর্কে এই পোস্টটি একবার দেখুন )
পাভেল

6
ভাল আমি এটি চাই না কারণ আমার এটির প্রয়োজন নেই। আমি কেবল কোনও কাঠামোর প্রয়োজনীয়তা মেটাতে ডিজাইনে অতিরিক্ত অপ্রয়োজনীয় জিনিস রাখার পছন্দ করি না। এটি কি আমাকে মেরে ফেলবে না ন্যাভ প্রোপ লাগাতে? না। আসলে আমি আপাতত এটি করেছি।
যৌক্তিকগীত

সম্পর্ক তৈরি করতে আপনার সর্বদা কমপক্ষে একদিকে নেভিগেশন সম্পত্তি প্রয়োজন। আরও তথ্যের জন্য স্ট্যাকওভারফ্লো.com
ওয়াহিদ বিটার

উত্তর:


63

ইএফ কোড প্রথম সাবলীল এপিআই সহ এটি অসম্ভব। ডাটাবেসে বিদেশী কী বাধা তৈরি করতে আপনার সর্বদা কমপক্ষে একটি নেভিগেশন সম্পত্তি প্রয়োজন।

আপনি যদি কোড ফার্স্ট মাইগ্রেশন ব্যবহার করেন তবে প্যাকেজ ম্যানেজার কনসোলটিতে নতুন কোড ভিত্তিক মাইগ্রেশন যুক্ত করার বিকল্প রয়েছে add-migration SomeNewSchemaName। আপনি যদি আপনার মডেল বা ম্যাপিংয়ের সাথে কিছু পরিবর্তন করেন তবে একটি নতুন স্থানান্তর যুক্ত করা হবে। আপনি যদি কিছু পরিবর্তন না করেন তবে নতুন মাইগ্রেশন ব্যবহার করে জোর করে add-migration -IgnoreChanges SomeNewSchemaName। এই ক্ষেত্রে মাইগ্রেশনটিতে কেবল খালি Upএবং Downপদ্ধতি থাকবে।

তারপরে আপনি Upপদ্ধতিটিতে ফলওয়ে যোগ করে এটি পরিবর্তন করতে পারেন :

public override void Up()
{
    // other stuff...

    AddForeignKey("ChildTableName", "ParentId", "ParentTableName", "Id",
        cascadeDelete: true); // or false
    CreateIndex("ChildTableName", "ParentId"); // if you want an index
}

এই মাইগ্রেশন চালানো ( update-databaseপ্যাকেজ পরিচালনা কনসোলে) এটির মতো এসকিউএল স্টেটমেন্ট চালাবে (এসকিউএল সার্ভারের জন্য):

ALTER TABLE [ChildTableName] ADD CONSTRAINT [FK_SomeName]
FOREIGN KEY ([ParentId]) REFERENCES [ParentTableName] ([Id])

CREATE INDEX [IX_SomeName] ON [ChildTableName] ([ParentId])

বিকল্পভাবে, মাইগ্রেশন ব্যতীত, আপনি কেবল একটি খাঁটি এসকিউএল কমান্ড ব্যবহার করে চালাতে পারেন

context.Database.ExecuteSqlCommand(sql);

যেখানে contextআপনার উদ্ভূত প্রসঙ্গ শ্রেণীর উদাহরণ রয়েছে এবং sqlস্ট্রিং হিসাবে কেবল উপরের এসকিউএল কমান্ড।

সচেতন থাকুন যে এই সমস্ত EF এর সাথে কোনও ParentIdসম্পর্ক নেই যা বিদেশী কী বলে কোনও ক্লু নেই । EF এটিকে কেবল একটি সাধারণ স্কেলারের সম্পত্তি হিসাবে বিবেচনা করবে। কেবলমাত্র একটি এসকিউএল পরিচালন সরঞ্জাম খোলার এবং হাত দ্বারা প্রতিবন্ধকতা যুক্ত করার তুলনায় উপরের সমস্তগুলি কেবল আরও জটিল এবং ধীর পথ।


4
সরলকরণটি অটোমেশন থেকে আসে: আমার কোডটি মোতায়েন করা অন্যান্য পরিবেশে আমার অ্যাক্সেস নেই। কোডে এই পরিবর্তনগুলি সম্পাদন করতে সক্ষম হওয়া আমার পক্ষে দুর্দান্ত। তবে আমি
স্নারকটি

আমি মনে করি আপনি সত্ত্বার উপরেও একটি বৈশিষ্ট্য সেট করেছেন, তাই প্যারেন্ট আইডিতে, কেবল যুক্ত করুন [ForeignKey("ParentTableName")]। যা মূল টেবিলে কীটি সম্পত্তি সাথে যুক্ত করবে। যদিও এখন আপনি একটি হার্ড কোডিং টেবিলের নাম পেয়েছেন।
ট্রায়ঙ্কো

4
এটি সুস্পষ্টভাবে অসম্ভব নয়, নীচের অন্যান্য মন্তব্য দেখুন কেন এটি এমনকি সঠিক উত্তর হিসাবে চিহ্নিত হয়েছে
আইগোর

111

যদিও এই পোস্টটির জন্য Entity Frameworkনয় Entity Framework Core, এটি কোনও ব্যক্তির পক্ষে কার্যকর হতে পারে যারা সত্তা ফ্রেমওয়ার্ক কোর ব্যবহার করে একই জিনিস অর্জন করতে চায় (আমি ভি 1.1.2 ব্যবহার করছি)।

আমার নেভিগেশন বৈশিষ্ট্যগুলির প্রয়োজন নেই (যদিও তারা দুর্দান্ত) কারণ আমি ডিডিডি অনুশীলন করছি এবং আমি চাই Parentএবং Childদুটি পৃথক সামগ্রিক মূল হতে চাই । আমি চাই তারা পরিকাঠামো-নির্দিষ্ট Entity Frameworkনেভিগেশন বৈশিষ্ট্যের মাধ্যমে নয় বরং বিদেশী কী মাধ্যমে একে অপরের সাথে কথা বলতে সক্ষম হোক ।

আপনাকে যা করতে হবে তা হল নেভিগেশন বৈশিষ্ট্যগুলি নির্দিষ্ট করে না দিয়ে HasOneএবং ব্যবহার WithManyনা করে একদিকে সম্পর্ক কনফিগার করা (তারা সব পরে নেই)।

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {}

    protected override void OnModelCreating(ModelBuilder builder)
    {
        ......

        builder.Entity<Parent>(b => {
            b.HasKey(p => p.Id);
            b.ToTable("Parent");
        });

        builder.Entity<Child>(b => {
            b.HasKey(c => c.Id);
            b.Property(c => c.ParentId).IsRequired();

            // Without referencing navigation properties (they're not there anyway)
            b.HasOne<Parent>()    // <---
                .WithMany()       // <---
                .HasForeignKey(c => c.ParentId);

            // Just for comparison, with navigation properties defined,
            // (let's say you call it Parent in the Child class and Children
            // collection in Parent class), you might have to configure them 
            // like:
            // b.HasOne(c => c.Parent)
            //     .WithMany(p => p.Children)
            //     .HasForeignKey(c => c.ParentId);

            b.ToTable("Child");
        });

        ......
    }
}

আমি পাশাপাশি কিভাবে কনফিগার করতে সত্তা বৈশিষ্ট্য উদাহরণ আউট দিচ্ছি, কিন্তু অধিকাংশ গুরুত্বপূর্ণ এখানে HasOne<>, WithMany()এবং HasForeignKey()

আশা করি এটা সাহায্য করবে.


8
এটি ইএফ কোরের সঠিক উত্তর এবং ডিডিডি অনুশীলনকারীদের জন্য এটি একটি আবশ্যক।
থিয়াগো সিলভা

4
নেভিগেশনাল সম্পত্তি অপসারণে কী পরিবর্তন হয়েছে সে সম্পর্কে আমি পরিষ্কার নই। আপনি দয়া করে পরিষ্কার করতে পারেন?
অ্যান্ড্রু.রকওয়েল

4
@ andrew.rockwell: দেখুন HasOne<Parent>()এবং .WithMany()thie শিশু কনফিগারেশনের উপর। এগুলি নেভিগেশন বৈশিষ্ট্যগুলি মোটেই রেফারেন্স করে না, যেহেতু কোনও নেভিগেশন বৈশিষ্ট্য কোনওভাবেই সংজ্ঞায়িত করা হয়নি। আমি আমার আপডেটগুলি দিয়ে আরও পরিষ্কার করার চেষ্টা করব।
ডেভিড লিয়াং

অসাধারণ. ধন্যবাদ @ ডেভিডলিয়াং
andrew.rockwell

4
@ মিরিন্ড 4 ওপিতে নির্দিষ্ট কোডের নমুনার সাথে সম্পর্কিত নয়, আপনি যদি তাদের নিজ নিজ ডিবি টেবিলগুলিতে বিভিন্ন সমষ্টিগত রুট সত্ত্বাকে ম্যাপিং করে থাকেন, ডিডিডি অনুসারে, এই রুট এনটাইটগুলি কেবল তাদের পরিচয়ের মাধ্যমে একে অপরকে রেফারেন্স করা উচিত এবং এতে একটি সম্পূর্ণ রেফারেন্স না থাকা উচিত অন্য এআর সত্তা। প্রকৃতপক্ষে, ডিডিডিতে সত্তা / পরিচয় / লগ / গাইড (বিশেষত এআর সত্তা) এর মতো আদিম ধরণের প্রপস ব্যবহার না করে সত্তার পরিচয়কে একটি মূল্য অবজেক্ট হিসাবে তৈরি করাও আদিম আবেগ এড়ানো এবং বিভিন্ন এআরকে মানের মাধ্যমে সত্তাগুলিকে রেফারেন্সের অনুমতি দেয় অবজেক্ট আইডি টাইপ। এইচটিএইচ
থিয়াগো সিলভা

21

তাদের জন্য ছোট ইঙ্গিত, যারা ডেটাঅনোটেশন ব্যবহার করতে চান এবং নেভিগেশন সম্পত্তি প্রকাশ করতে চান না - ব্যবহার করুন protected

public class Parent
{
    public int Id { get; set; }
}
public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }

    protected virtual Parent Parent { get; set; }
}

এটি - এটির সাথে বিদেশী কী তৈরি cascade:trueকরা Add-Migrationহবে।


4
এটি এমনকি ব্যক্তিগতভাবেও করতে পারে
মার্ক উইট্কে

4
শিশু তৈরি করার সময় আপনাকে কি বরাদ্দ করতে হবে Parentবা কেবল ParentId?
জর্জ মাউয়ার

4
@ মার্কউইটকে virtualসম্পত্তি থাকতে পারে না private
লিনকিউ

@ জর্জিমার: এটি একটি ভাল প্রশ্ন! প্রযুক্তিগতভাবে হয় যে কোনও একটি কাজ করবে, তবে এটির ক্ষেত্রেও সমস্যা হয়ে দাঁড়ায় যখন আপনার মতো এই মতো বেমানান কোড রয়েছে, কারণ বিকাশকারীরা (বিশেষত নতুন আগত) কী পাস করবেন তা নিশ্চিত নন
ডেভিড লিয়াং

14

EF কোর ক্ষেত্রে আপনার অগত্যা কোনও নেভিগেশন সম্পত্তি সরবরাহ করার প্রয়োজন নেই। সম্পর্কের একদিকে আপনি কেবল একটি বিদেশী কী সরবরাহ করতে পারেন। সাবলীল এপিআই সহ একটি সাধারণ উদাহরণ:

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace EFModeling.Configuring.FluentAPI.Samples.Relationships.NoNavigation
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
             modelBuilder.Entity<Post>()
                .HasOne<Blog>()
                .WithMany()
                .HasForeignKey(p => p.BlogId);
        }
    }

    public class Blog
    {
         public int BlogId { get; set; }
         public string Url { get; set; }
    }

    public class Post
    {
         public int PostId { get; set; }
         public string Title { get; set; }
         public string Content { get; set; }

        public int BlogId { get; set; }
    }
}

2

আমি। নেট কোর 3.1, সত্তা ফ্রেমওয়ার্ক 3.1.3 ব্যবহার করছি। আমি চারপাশে অনুসন্ধান করে যাচ্ছি এবং আমি যে সমাধানটি নিয়ে এসেছি সেটির জেনেরিক সংস্করণটি ব্যবহার করা হয়েছিল HasForeginKey<DependantEntityType>(e => e.ForeginKeyProperty)। আপনি এর মতো একটি সম্পর্কে একটি সম্পর্ক তৈরি করতে পারেন:

builder.entity<Parent>()
.HasOne<Child>()
.WithOne<>()
.HasForeginKey<Child>(c => c.ParentId);

builder.entity<Child>()
    .Property(c => c.ParentId).IsRequired();

আশা করি এটি কীভাবে HasForeginKeyপদ্ধতিটি ব্যবহার করতে পারে সে সম্পর্কে সহায়তা করে বা কমপক্ষে কিছু অন্যান্য ধারণা সরবরাহ করে ।


0

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

এবং আমার কাছে আলাদা মাইগ্রেশন অ্যাপ্লিকেশন রয়েছে, যা মাইগ্রেশনগুলির জন্য ব্যবহৃত হয় (আমি অটোমাইগ্রেশন ব্যবহার করি) এবং প্রাথমিক ডিবি তৈরির জন্য। এই প্রকল্পটি সুস্পষ্ট কারণে সমস্ত কিছু উল্লেখ করে।

সমাধান সি স্টাইল:

  • লিঙ্কের মাধ্যমে মাইগ্রেশন প্রকল্পে টার্গেট ক্লাসের সাথে "অনুলিপি" ফাইল ( altভিএস -তে কী সহ ড্রাগ-এন-ড্রপ )
  • নাগিভিশন সম্পত্তি (এবং এফকে বৈশিষ্ট্য) এর মাধ্যমে অক্ষম করুন #if _MIGRATION
  • মাইগ্রেশন অ্যাপ্লিকেশনে সেই প্রিপ্রসেসর সংজ্ঞা সেট করুন এবং মডেল প্রকল্পে সেট করবেন না, সুতরাং এটি কোনও বিষয় উল্লেখ করবে না ( Contactউদাহরণস্বরূপ শ্রেণীর সাথে অ্যাসেম্বলি রেফারেন্স করবেন না )।

নমুনা:

    public int? ContactId { get; set; }

#if _MIGRATION
    [ForeignKey(nameof(ContactId))]
    public Contact Contact { get; set; }
#endif

অবশ্যই আপনার একইভাবে usingনির্দেশকে অক্ষম করা উচিত এবং নেমস্পেস পরিবর্তন করা উচিত ।

তারপরে সমস্ত গ্রাহকরা সেই সম্পত্তি যথারীতি ডিবি ক্ষেত্র হিসাবে ব্যবহার করতে পারেন (এবং অতিরিক্ত সংঘের প্রয়োজন না হলে রেফারেন্স দেবেন না), তবে ডিবি সার্ভার জানতে পারবে যে এটি এফকে এবং ক্যাসকেডিং ব্যবহার করতে পারে। খুব নোংরা সমাধান। কিন্তু কাজ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.