1. ent এন্টিটি অপারেশন নিয়ে পরিচিতি

এই টিউটোরিয়ালে আপনাকে ent ফ্রেমওয়ার্কে এন্টিটি অপারেশন মাস্টার করার জন্য একটি সম্পূর্ণ গাইড দেয়া হবে, যা এন্টিটি তৈরি, প্রশ্ন করা, আপডেট করা, এবং মুছে ফেলা প্রক্রিয়া অনুযায়ী পুরো ধারণা দেয়। এটি ent এর মৌলিক কার্যকারিতা ধারণ করার জন্য নতুনদের জন্য উপযোগী।

3. এন্টিটি তৈরি অপারেশন

3.1 একটি এন্টিটি তৈরি করা

একটি এন্টিটি তৈরি করা তথ্য ধারণের জন্য মৌলিক অপারেশন। নীচে দেওয়া হল কিভাবে ent ফ্রেমওয়ার্ক ব্যবহার করে একটি এন্টিটি অবজেক্ট তৈরি এবং ডেটাবেসে সেই অবজেক্ট সেভ করতে হয়।

  1. প্রথমে, এন্টিটির স্ট্রাকচার এবং ফিল্ডগুলির স্থান নির্ধারণ করুন, অর্থাৎ schema ফাইলে এন্টিটির মডেল নির্ধারণ করুন।
  2. সাথে ent generate কমান্ড চালানো যাতে সাথে যুক্ত এন্টিটি অপারেশন কোড জেনারেট হয়।
  3. তৈরি হয়ে যাওয়া Create মেথড ব্যবহার করুন এবং চেইনড কলে এন্টিটির ফিল্ড মান নির্ধারণ করুন।
  4. শেষে, এন্টিটি ডেটাবেসে সেভ করতে Save মেথড কল করুন।

নিচে দেওয়া হল কিভাবে একটি ইউজার এন্টিটি তৈরি করা এবং সেভ করা হয়েছে:

package main

import (
    "context"
    "log"
    "entdemo/ent"
)

func main() {
    // ডাটাবেস ইন্টারঅ্যাকশনের জন্য একটি ক্লায়েন্ট ইন্সট্যান্স তৈরি করুন
    client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
    if err != nil {
        log.Fatalf("ডেটাবেস সংযোগ খোলার সময় ব্যর্থ হয়েছে: %v", err)
    }
    defer client.Close()

    // একটি কনটেক্সট তৈরি করুন
    ctx := context.Background()
    
    // ক্লায়েন্ট ব্যবহার করে একটি ইউজার এন্টিটি তৈরি করুন
    a8m, err := client.User.
        Create().
        SetName("a8m").
        Save(ctx)
    if err != nil {
        log.Fatalf("ইউজার এন্টিটি তৈরি করতে ব্যর্থ হয়েছে: %v", err)
    }

    // এন্টিটি সফলভাবে ডেটাবেসে সেভ হয়েছে
    log.Printf("ইউজার এন্টিটি সেভ হয়েছে: %v", a8m)
}

এই উদাহরণে, প্রথমে ডাটাবেস ক্লায়েন্ট client তৈরি করা হয়েছে। তারপরে, User.Create মেথড ব্যবহার করে নতুন ইউজারের বৈশিষ্ট্যগুলি নির্ধারণ করা হয়, এবং শেষে Save মেথড কল করে ইউজারকে ডেটাবেসে সেভ করা হয়।

3.2 ব্যাচ এন্টিটি তৈরি

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

ব্যাচ এন্টিটি সৃষ্টির জন্য পদক্ষেপগুলি হল:

  1. Create মেথডের পরিবর্তে CreateBulk মেথড ব্যবহার করুন, যা একটি এন্টিটি সৃষ্টি করার একটি সিঙ্গেল অপারেশন সৃষ্টি করে।
  2. প্রতিটি অনুষ্ঠানের জন্য Create কল করুন।
  3. সমস্ত এন্টিটি তৈরি হয়ে গেলে, Save মেথড ব্যবহার করে সমস্ত এন্টিটিকে ডেটাবেসে বাল্কে সেভ করুন।

নিচে দেওয়া হল ব্যাচ এন্টিটি সৃষ্টির উদাহরণ:

package main

import (
    "context"
    "log"
    "entdemo/ent"
)

func main() {
    client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
    if err != nil {
        log.Fatalf("ডেটাবেস সংযোগ খোলার সময় ব্যর্থ হয়েছে: %v", err)
    }
    defer client.Close()
    ctx := context.Background()

    // ব্যাচে Pet এন্টিটিগুলি তৈরি করুন
    pets, err := client.Pet.CreateBulk(
        client.Pet.Create().SetName("pedro").SetOwner(a8m),
        client.Pet.Create().SetName("xabi").SetOwner(a8m),
        client.Pet.Create().SetName("layla").SetOwner(a8m),
    ).Save(ctx)
    if err != nil {
        log.Fatalf("পেট এন্টিটি ব্যাচে তৈরি করতে ব্যর্থ হয়েছে: %v", err)
    }

    log.Printf("ব্যাচে %d টি পেট এন্টিটি তৈরি করা হয়েছে\n", len(pets))
}

এই উদাহরণে, প্রথমে একটি client তৈরি করা হয়েছে, এবং তারপরে CreateBulk মেথড ব্যবহার করে এনের নাম এবং মালিকের ফিল্ড নির্ধারণ করে একাধিক Pet এন্টিটি নির্মাণ করা হয়। সমস্ত এন্টিটির সেভ মেথড কল করা হল একবারে ডেটা সংক্রান্ত যাত্রা ব্যবহারের উপর ভালো কাজ করে।

4. এন্টিটি প্রশ্নের অপারেশন

4.1 মৌলিক কুয়েরি

ডাটাবেস কুয়েরি করা তথ্য পেতের মৌলিক উপায়। ent-এ, Query মেথডটি একটি কুয়েরি শুরু করতে ব্যবহৃত হয়। নীচে মৌলিক এক্সিকিউটি কুয়েরির পদক্ষেপ এবং একটি উদাহরণ দেওয়া হল:

  1. নিশ্চিত করুন আপনি একটি ব্যবহায়যোগ্য Client ইনস্ট্যান্স রয়েছেন।
  2. Client.Query() বা Pet.Query() এরকম এন্টিটি হেল্পার মেথড ব্যবহার করুন একটি কুয়েরি তৈরি করতে।
  3. প্রয়োজনে অব্যাহতি সহিত ফিল্টারিং শর্ত যোগ করুন, যেমন Where
  4. কুয়েরি নিষ্পাদন করুন এবং All মেথডটি কল করে ফলাফল পেতে।
// মেইন ফাংশন
package main

import (
    "context"
    "log"
    "entdemo/ent"
    "entdemo/ent/user"
)

func main() {
    client, err := ent.Open("sqlite3", "file:ent?cache=shared&_fk=1")
    if err != nil {
        log.Fatalf("ডাটাবেস সংযোগ খোলা যায়নি: %v", err)
    }
    defer client.Close()
    ctx := context.Background()

    // "a8m" নামের সব ব্যবহারকারী কুয়েরি করুন
    users, err := client.User.
        Query().
        Where(user.NameEQ("a8m")).
        All(ctx)
    if err != nil {
        log.Fatalf("ব্যবহারকারীদের কুয়েরি করা ব্যর্থ হয়েছে: %v", err)
    }

    for _, u := range users {
        log.Printf("ব্যবহারকারী পাওয়া গিয়েছে: %#v\n", u)
    }
}

উদাহরণটি প্রদর্শন করে যেভাবে "a8m" নামের সব ব্যবহারকারী খুঁজে বের করা হয়।

4.2 পৃষ্ঠাবর্তনী এবং সাজানো

পৃষ্ঠাবর্তনী এবং সাজানো হল কুয়েরি করার সময় প্রযোজনীয় উন্নত বৈশিষ্ট্য। এটি তথ্যের আউটপুট অর্ডার এবং পরিমাণ নিয়ন্ত্রণ করার জন্য ব্যবহৃত হয়। ent ব্যবহার করে পৃষ্ঠাবর্তনী এবং সাজানো কুয়েরি করার উদাহরণ:

  1. অতিক্রম করতে Limit মেথড ব্যবহার করুন যে ফলাফলের সর্বাধিক সংখ্যা ঠিক করবে।
  2. পূর্বের ফলাফলের কিছু অতিক্রম করতে Offset মেথড ব্যবহার করুন।
  3. সাজানো ক্ষেত্র এবং নির্দেশ নির্ধারণ করতে Order মেথড ব্যবহার করুন।

এখানে পৃষ্ঠাবর্তনী এবং সাজানোর একটি উদাহরণ:

// মেইন ফাংশন
package main

import (
    "context"
    "log"
    "entdemo/ent"
    "entdemo/ent/pet"
)

func main() {
    client, err := ent.Open("sqlite3", "file:ent?cache=shared&_fk=1")
    if err != nil {
        log.Fatalf("ডাটাবেস সংযোগ খোলা যায়নি: %v", err)
    }
    defer client.Close()
    ctx := context.Background()

    // বয়সের অবস্থানে অবতরণ পাল্টান Pets কুয়েরি করুন
    pets, err := client.Pet.
        Query().
        Order(ent.Desc(pet.FieldAge)).
        Limit(10).
        Offset(0).
        All(ctx)
    if err != nil {
        log.Fatalf("প্রাণী কুয়েরি করা ব্যর্থ হয়েছে: %v", err)
    }

    for _, p := range pets {
        log.Printf("প্রাণী পাওয়া গিয়েছে: %#v\n", p)
    }
}

এই উদাহরণটি দেখায় যেভাবে বয়সের অবস্থানে পাল্টানো সাজানো প্রাণীর প্রথম পৃষ্ঠা প্রাপ্ত করা হয়। Limit এবং Offset এর মান পরিবর্তন করে, আপনি সমগ্র ডেটাসেট মাধ্যমে পৃষ্ঠাবর্তনী অর্জন করতে পারেন।

5. এন্টিটি আপডেট অপারেশন

5.1 একক এন্টিটি আপডেট

অনেক অ্যাপ্লিকেশনে, এন্টিটি আপডেট করা দৈনন্দিন অপারেশনের অসীম অংশ। এই বিভাগে, আমরা দেখাব কীভাবে এন্ট ফ্রেমওয়ার্ক ব্যবহার করে ডাটাবেসে একক এন্টিটি আপডেট করতে হয়।

প্রথমত, মানিঃ আমরা মানি঍ বয়স আপডেট করতে হবে, তাহলে আমরা এন্ট দ্বারা তৈরি করা Update মেথড ব্যবহার করতে পারি।

// কিন্তু আমাদের যদি পারিতে "a8m" ইউজার কোনো এন্টিটি আপডেট করতে হবে তাহলে

a8m, err := a8m.Update().         // একটি ব্যবহারকারী আপডেট বিল্ডার তৈরি করুন
    SetAge(30).                   // ব্যবহারকারীর বয়স সেট করুন 30 বছর
    Save(ctx)                     // সেভ অপারেশনটি চালান এবং ফলস্বরূপ প্রাপ্তির ফল ফেরত দিন
if err != nil {
    log.Fatalf("ব্যবহারকারী আপডেট করতে ব্যর্থ হয়েছে: %v", err)
}

আপনি একাধিক ক্ষেত্র পরিবর্তন করতে অবশ্যই এদের সাথে মিশান করতে পারেন:

a8m, err := a8m.Update().
    SetAge(30).                    // বয়স আপডেট করুন
    SetName("Ariel").              // নাম আপডেট করুন
    AddRank(10).                   // র্যাঙ্কে 10 যোগ করুন
    Save(ctx)
if err != nil {
    log.Fatalf("ব্যবহারকারী আপডেট করতে ব্যর্থ হয়েছে: %v", err)
}

আপডেট অপারেশনটি চেইন করা যায়, যা খুব মলদার এবং সহজে পড়া। Save মেথডটি কল করা হলে আপডেট করা হবে এবং আপডেট এন্টিটি বা একটি ত্রুটি বার্তা ফিরিয়ে দেয়।

5.2 শর্তমূলক আপডেট

Ent আপনাকে শর্তানুযায়ী আপডেট করতে অনুমতি দেয়। এখানে একটি উদাহরণ দে৓ও হলো যেখানে কেবলমাত্র নির্ধারিত শর্ত পূরণ করে কেবলমাত্র ব্যবহারকারী সম্পর্কিত আপডেট করা হবে।

// ধরা যাক আমাদের একজন ব্যবহারকারীর `id` আছে এবং আমরা ঐ ব্যবহারকারীকে বর্তমান সংস্করণে সম্পূর্ণ চিহ্নিত করতে চাই।

err := client.Todo.
    UpdateOneID(id).          // ব্যবহারকারী আইডি দিয়ে আপডেট করার জন্য একটি বিল্ডার তৈরি করুন
    SetStatus(todo.StatusDone).
    AddVersion(1).
    Where(
        todo.Version(currentVersion),  // আপডেট অপারেশনটি শুধুমাত্র বর্তমান সংস্করণের সাথে মেলা হলেই অনুষ্ঠিত হবে
    ).
    Exec(ctx)
switch {
case ent.IsNotFound(err):
    fmt.Println("টুডো পাওয়া যায়নি")
case err != nil:
    fmt.Println("আপডেট সমস্যা:", err)
}

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

6. অবজেক্ট মুছে ফেলার অপারেশন

6.1 একক অবজেক্ট মুছে ফেলা

ডেটাবেস অপারেশনে অবজেক্টের মুছে ফেলা আরও একটি গুরুত্বপূর্ণ ফাংশন। Ent ফ্রেমওয়ার্ক ডিলেট অপারেশন অংশের জন্য একটি সহজ API প্রদান করে।

নিচের উদাহরণটি দেখায় যেখানে দেওয়া ব্যবহারকারী অবজেক্ট মুছে ফেলার উপায়ঃ

err := client.User.
    DeleteOne(a8m).  // ব্যবহারকারী মুছে ফেলার বিল্ডার তৈরি করুন
    Exec(ctx)        // মুছে ফেলার অপারেশনটি অভিযান করুন
if err != nil {
    log.Fatalf("ব্যবহারকারী মুছে ফেলতে ব্যর্থ হয়েছে: %v", err)
}

6.2 শর্তমূলক মুছে ফেলা

আপডেট অপারেশনের মতো, আমরা নির্দিষ্ট শর্ত অনুসারে মুছে ফেলে অপারেশন অংশ চালাতে পারি। নির্দিষ্ট অবস্থানগুলি পূরণ করতে আমরা .Where() মেথড ব্যবহার করতে পারি:

// ধরা যাক আমরা একটি নির্দিষ্ট তারিখের আগে হওয়া সকল ফাইল মুছে ফেলতে চাই

affected, err := client.File.
    Delete().
    Where(file.UpdatedAtLT(date)).  // মুছে ফেলা শুধুমাত্র ঐ তারিখের আগে ফাইলের আপডেট সময় হওয়া থাকলেই অনুষ্ঠান করা হবে
    Exec(ctx)
if err != nil {
    log.Fatalf("ফাইল মুছে ফেলতে ব্যর্থ হয়েছে: %v", err)
}

// এই অপারেশনটি মুছে ফেলা অবশ্যই জন্য দ্রুত কন্ট্রোল ও নিশ্চিততা সহযোগিতা করে। এটি নিশ্চিত করে যে শুধুমাত্র ব্যাপারিকভাবে নির্ধারিত শর্তগুলি পূরণ করা হয়। এটি ডাটাবেজ অপারেশনের নিরাপত্তা এবং বিশ্বস্ততা বাড়িয়ে তোলে।