简体   繁体   中英

How can I do it ? I don't want to add same record in database with Entity Framework

What methods can I use Find, FirstOrDefault, Any....

public virtual void Add(T entity)
{
        using (MovieAppContext _context = new MovieAppContext())
        {
            var record = _context.Set<T>().Find(entity); // does not work I got e

            if (record == null)
            {
                _context.Set<T>().Add(entity);
                _context.SaveChanges();
            }
        }
}

Given your scope here, DbSet<T>.Find<T>(params object[]) is probably not the method you should be using.


The following solution uses IQueryable<T>.Any<T>(Expression<Func<T, bool>>) , a Linq Extension Method that accepts a Predicate\Function.

Code Sample using it

using (MovieAppContext _context = new MovieAppContext())
{
    bool queryResult = _context.Set<T>().Any((e) => e.Name.Equals(entity.Name, StringComparison.OrdinalIgnoreCase));

    if (queryResult)
    {
        _context.Set<T>().Add(entity);
        _context.SaveChanges();
    }
}

Here, we are defining an anonymous function delegate, Func<T, bool> , that is in turn being used to define a Linq Expression, Expression<Func<T, bool>> .


Note

I defined this function predicate expression to evaluate on the entity names (a made-up property of this type; that in this example portrays a unique constraint.)

Also, an alternative to using anonymous functions declaration for this expression is to declare it, then pass it.

That looks like the following:

...
Expression<Func<T, bool>> WhereEntityNameMatches = (e) => e.Name.Equals(entity.Name, StringComparison.OrdinalIgnoreCase));
    
bool queryResult = _context.Set<T>().Any(WhereEntityNameMatches);
...

Which may help out with reusability and scope considerations.

For consideration, An alternative here would be to not attempt the query lookup and check at all.

Instead, you would do a try-catch for DbUpdateException in the attempt to save changes after\following this Add operation.

try 
{
    _context.Set<T>().Add(entity);
    _context.SaveChanges();
} 
catch (DbUpdateException) 
{
    var isRaisedByUniqueIndexOrConstraint = new[] { "2601", "2627" }.Contains(ex.GetBaseException().Data["HelpLink.EvtID"]) ?? false;

    if (!isRaisedByUniqueIndexOrConstraint)
        throw;

    // Could suppress and\or handle attempted duplicate record adding
}

This relies on those index\constraints existing, so you would first define a Unique Index on the column(s) (as well as your entity type using Data Annotations: IndexAttribute ).


Note

Part of this answer\solution purposes getting the Error Number from ADO.NET SqlClient Base Exception to further scope and qualify the cause of exception. The Error Numbers, "2601", "2627" , are hard-coded in this example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM