sql - সফটওয - রিলেশন ডেটা মডেলের প্রবর্তক কে




কিভাবে এন্টিটি ফ্রেমওয়ার্ক ব্যবহার করে শুধুমাত্র একটি ক্ষেত্র আপডেট করতে? (10)

Entity Framework DbContext এর মাধ্যমে ডেটাবেস থেকে আপনার জিজ্ঞাসিত বস্তুর উপর আপনার পরিবর্তনগুলি ট্র্যাক করে। উদাহরণস্বরূপ, যদি আপনি DbContext ইনস্ট্যান্স নামটি dbContext হয়

public void ChangePassword(int userId, string password){
     var user = dbContext.Users.FirstOrDefault(u=>u.UserId == userId);
     user.password = password;
     dbContext.SaveChanges();
}

এখানে টেবিল

ব্যবহারকারীরা

UserId
UserName
Password
EmailAddress

এবং কোড ..

public void ChangePassword(int userId, string password){
//code to update the password..
}

EntityFramework Core 2.x এ Attach দরকার নেই:

 // get a tracked entity
 var entity = context.User.Find(userId);
 entity.someProp = someValue;
 // other property changes might come here
 context.SaveChanges();

এসকিউএল সার্ভারে এটি চেষ্টা এবং এটি প্রোফাইল:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [User] SET [someProp] = @p0
WHERE [UserId] = @p1;
SELECT @@ROWCOUNT;

',N'@p1 int,@p0 bit',@p1=1223424,@p0=1

ইতিমধ্যে লোড হওয়া সত্তাগুলি একটি নির্বাচন ট্রিগার না করে এবং এটি স্বয়ংক্রিয়ভাবে প্রয়োজন হলে সত্তাটিকে সংযুক্ত করে তা নিশ্চিত করুন (ডক্স থেকে):

    ///     Finds an entity with the given primary key values. If an entity with the given primary key values
    ///     is being tracked by the context, then it is returned immediately without making a request to the
    ///     database. Otherwise, a query is made to the database for an entity with the given primary key values
    ///     and this entity, if found, is attached to the context and returned. If no entity is found, then
    ///     null is returned.

আপনি মূলত দুটি বিকল্প আছে:

  • EF পথ সব পথ যেতে, যে ক্ষেত্রে, আপনি চাই
    • ব্যবহারকারীর উপর ভিত্তি করে বস্তুটি লোড করুন - যদি পুরো বস্তুটি লোড হয়ে যায়
    • password ক্ষেত্র আপডেট করুন
    • প্রসঙ্গটি ব্যবহার করে বস্তুটি আবার সংরক্ষণ করুন। .SaveChanges() পদ্ধতি

এই ক্ষেত্রে, এটি বিস্তারিতভাবে এই হ্যান্ডেল কিভাবে EF পর্যন্ত। আমি শুধু এটি পরীক্ষা করেছি, এবং এই ক্ষেত্রে আমি শুধুমাত্র একটি বস্তুর একটি ক্ষেত্র পরিবর্তন করতে পারি, যা EF তৈরি করে সেটিই আপনি যা নিজে তৈরি করতে চান তা অনেক বেশি - কিছু ভালো:

`UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId`

সুতরাং EF আসলে কোন কলামগুলি প্রকৃতপক্ষে পরিবর্তিত হয়েছে তা নির্ধারণ করার জন্য যথেষ্ট স্মার্ট এবং এটি কেবলমাত্র সেই আপডেটগুলি পরিচালনা করার জন্য একটি টি-এসকিউএল বিবৃতি তৈরি করবে।

  • আপনি T-SQL কোডে (ঠিক কোনও UserId জন্য Password কলামটি আপডেট করুন এবং অন্য কিছুই নয় - মূলত UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId ) সংরক্ষণ করে এমন একটি সংরক্ষিত পদ্ধতি সংজ্ঞায়িত করুন এবং আপনি আপনার EF মডেলের সেই সংরক্ষিত পদ্ধতির জন্য একটি ফাংশন আমদানি তৈরি করুন এবং আপনি উপরে বর্ণিত পদক্ষেপগুলি করার পরিবর্তে এই ফাংশনটি কল করুন

আমি ValueInjecter nuget ব্যবহার করে ValueInjecter এন্টিটির মধ্যে বাইন্ডিং মডেলকে ইনজেকশন করার জন্য নিম্নলিখিত ব্যবহার করে:

public async Task<IHttpActionResult> Add(CustomBindingModel model)
{
   var entity= await db.MyEntities.FindAsync(model.Id);
   if (entity== null) return NotFound();

   entity.InjectFrom<NoNullsInjection>(model);

   await db.SaveChangesAsync();
   return Ok();
}

কাস্টম কনভেনশন ব্যবহার লক্ষ্য করুন যে যদি তারা সার্ভার থেকে নাল থাকে তবে বৈশিষ্ট্য আপডেট করে না।

ValueInjecter v3 +

public class NoNullsInjection : LoopInjection
{
    protected override void SetValue(object source, object target, PropertyInfo sp, PropertyInfo tp)
    {
        if (sp.GetValue(source) == null) return;
        base.SetValue(source, target, sp, tp);
    }
}

ব্যবহার:

target.InjectFrom<NoNullsInjection>(source);

মান ইনজেক্টর ভি 2

এই উত্তর সন্ধান করুন

বিচারকার্য স্থগিত রাখার আদেশ

সম্পত্তিটি ইচ্ছাকৃতভাবে নল থেকে সরানো হয়েছে কিনা তা আপনি জানেন না বা এটির কোনো মূল্য নেই। অন্য কথায়, সম্পত্তি মানটি শুধুমাত্র অন্য মানের সাথে প্রতিস্থাপিত হতে পারে তবে সাফ করা হয় না।


আমি এখানে দেরিতে দেরিতে আছি, কিন্তু এভাবেই আমি এটা করছি, আমি এমন সময় কাটানোর সময় কাটিয়েছি যেটি আমি সাশ্রয়ী ছিলাম; এটি পরিবর্তিত ক্ষেত্রগুলির জন্য শুধুমাত্র একটি UPDATE বিবৃতি উত্পন্ন করে, কারণ আপনি কোনও "সাদা তালিকা" ধারণার মাধ্যমে তারা যা বোঝায় তা স্পষ্টভাবে সংজ্ঞায়িত করে যা কোনওভাবে ওয়েব ফর্ম ইনজেকশন রোধে আরও সুরক্ষিত।

আমার ISATION তথ্য সংগ্রহস্থল থেকে একটি উদ্ধৃতি:

public bool Update<T>(T item, params string[] changedPropertyNames) where T 
  : class, new()
{
    _context.Set<T>().Attach(item);
    foreach (var propertyName in changedPropertyNames)
    {
        // If we can't find the property, this line wil throw an exception, 
        //which is good as we want to know about it
        _context.Entry(item).Property(propertyName).IsModified = true;
    }
    return true;
}

এটি যদি আপনি চান তবে কটাক্ষপাত করা যেতে পারে। তবে আমি এই পরিপ্রেক্ষিতে ব্যতিক্রম সম্পর্কে জানার জন্য ব্যক্তিগতভাবে আমার কলারকে পছন্দ করি।

এটি এই ফ্যাশনের মত কিছু বলা হবে (আমার জন্য, এটি একটি ASP.NET ওয়েব API এর মাধ্যমে ছিল):

if (!session.Update(franchiseViewModel.Franchise, new[]
    {
      "Name",
      "StartDate"
  }))
  throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));

আমি এটা ব্যবহার করছি

সত্তা:

public class Thing 
{
    [Key]
    public int Id { get; set; }
    public string Info { get; set; }
    public string OtherStuff { get; set; }
}

dbcontext:

public class MyDataContext : DbContext
{
    public DbSet<Thing > Things { get; set; }
}

প্রবেশাধিকার কোড:

MyDataContext ctx = new MyDataContext();

// FIRST create a blank object
Thing thing = ctx.Things.Create();

// SECOND set the ID
thing.Id = id;

// THIRD attach the thing (id is not marked as modified)
db.Things.Attach(thing); 

// FOURTH set the fields you want updated.
thing.OtherStuff = "only want this field updated.";

// FIFTH save that thing
db.SaveChanges();

আমি প্রস্তাব উত্থাপন বিভিন্ন পরামর্শ মিশ্রন:

    async Task<bool> UpdateDbEntryAsync<T>(T entity, params Expression<Func<T, object>>[] properties) where T : class
    {
        try
        {
            var entry = db.Entry(entity);
            db.Set<T>().Attach(entity);
            foreach (var property in properties)
                entry.Property(property).IsModified = true;
            await db.SaveChangesAsync();
            return true;
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("UpdateDbEntryAsync exception: " + ex.Message);
            return false;
        } 
    }

দ্বারা বলা

UpdateDbEntryAsync(dbc, d => d.Property1);//, d => d.Property2, d => d.Property3, etc. etc.);

অথবা দ্বারা

await UpdateDbEntryAsync(dbc, d => d.Property1);

অথবা দ্বারা

bool b = UpdateDbEntryAsync(dbc, d => d.Property1).Result;

এই সমস্যার সমাধান খোঁজার সময়, আমি প্যাট্রিক ডিজজার্ডিনের ব্লগের মাধ্যমে গনিয়েলের উত্তরের একটি বৈচিত্র্য খুঁজে পেয়েছি:

public int Update(T entity, Expression<Func<T, object>>[] properties)
{
  DatabaseContext.Entry(entity).State = EntityState.Unchanged;
  foreach (var property in properties)
  {
    var propertyName = ExpressionHelper.GetExpressionText(property);
    DatabaseContext.Entry(entity).Property(propertyName).IsModified = true;
  }
  return DatabaseContext.SaveChangesWithoutValidation();
}

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

...Update(Model, d=>d.Name);
//or
...Update(Model, d=>d.Name, d=>d.SecondProperty, d=>d.AndSoOn);

(এখানে কিছুটা অনুরূপ সমাধান দেওয়া হয়েছে: https://.com/a/5749469/2115384 )

যে পদ্ধতিটি আমি বর্তমানে নিজের কোডে ব্যবহার করছি , সেটি এক্সপ্রেশন টাইপ। এটি আমার ক্ষেত্রে প্রয়োজনীয় ছিল, উদাহরণস্বরূপ Guid এবং অন্যান্য বস্তুর বৈশিষ্ট্যগুলির সাথে। যারা একটি রূপান্তর () মধ্যে 'আবৃত' ছিল এবং অতএব System.Web.Mvc.ExpressionHelper.GetExpressionText দ্বারা পরিচালিত না।

public int Update(T entity, Expression<Func<T, object>>[] properties)
{
    DbEntityEntry<T> entry = dataContext.Entry(entity);
    entry.State = EntityState.Unchanged;
    foreach (var property in properties)
    {
        string propertyName = "";
        Expression bodyExpression = property.Body;
        if (bodyExpression.NodeType == ExpressionType.Convert && bodyExpression is UnaryExpression)
        {
            Expression operand = ((UnaryExpression)property.Body).Operand;
            propertyName = ((MemberExpression)operand).Member.Name;
        }
        else
        {
            propertyName = System.Web.Mvc.ExpressionHelper.GetExpressionText(property);
        }
        entry.Property(propertyName).IsModified = true;
    }

    dataContext.Configuration.ValidateOnSaveEnabled = false;
    return dataContext.SaveChanges();
}

লাদিস্লাভের উত্তরটি ডিবি কনটেক্সট (EF 4.1 এ উপস্থাপিত) ব্যবহার করার জন্য আপডেট হয়েছে:

public void ChangePassword(int userId, string password)
{
  var user = new User() { Id = userId, Password = password };
  using (var db = new MyEfContextName())
  {
    db.Users.Attach(user);
    db.Entry(user).Property(x => x.Password).IsModified = true;
    db.SaveChanges();
  }
}

public async Task<bool> UpdateDbEntryAsync(TEntity entity, params Expression<Func<TEntity, object>>[] properties)
{
    try
    {
        this.Context.Set<TEntity>().Attach(entity);
        EntityEntry<TEntity> entry = this.Context.Entry(entity);
        entry.State = EntityState.Modified;
        foreach (var property in properties)
            entry.Property(property).IsModified = true;
        await this.Context.SaveChangesAsync();
        return true;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}






dbcontext