C# 我怎么做?我不知道';我不想在具有实体框架的数据库中添加相同的记录

C# 我怎么做?我不知道';我不想在具有实体框架的数据库中添加相同的记录,c#,entity-framework,C#,Entity Framework,我可以使用什么方法查找、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 (rec

我可以使用什么方法查找、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();
            }
        }
}
公共虚空添加(T实体)
{
使用(MovieAppContext _context=new MovieAppContext())
{
var record=_context.Set().Find(entity);//不起作用
if(记录==null)
{
_context.Set().Add(实体);
_SaveChanges();
}
}
}

鉴于您在此处的范围,
DbSet.Find(params object[])
可能不是您应该使用的方法


以下解决方案使用
IQueryable.Any(表达式)
,这是一种接受谓词\函数的Linq扩展方法

使用它的代码示例
使用(MovieAppContext\u context=new MovieAppContext())
{
bool queryResult=_context.Set().Any((e)=>e.Name.Equals(entity.Name,StringComparison.OrdinalIgnoreCase));
如果(查询结果)
{
_context.Set().Add(实体);
_SaveChanges();
}
}
在这里,我们定义了一个匿名函数委托,
Func
,它又被用来定义一个Linq表达式,
Expression


笔记 我定义了这个函数谓词表达式来对实体名称进行求值(这种类型的组合属性;在本例中描述了一个唯一的约束)

此外,对该表达式使用匿名函数声明的另一种方法是声明它,然后传递它

如下所示:

...
Expression<Func<T, bool>> WhereEntityNameMatches = (e) => e.Name.Equals(entity.Name, StringComparison.OrdinalIgnoreCase));
    
bool queryResult = _context.Set<T>().Any(WhereEntityNameMatches);
...
。。。
表达式WhereEntityNameMatches=(e)=>e.Name.Equals(entity.Name,StringComparison.OrdinalIgnoreCase));
bool queryResult=\u context.Set().Any(WhereEntityNameMatches);
...

这可能有助于解决可重用性和范围问题。

考虑到这一点,这里的另一种选择是根本不尝试查询查找和检查

相反,在执行此
Add
操作后,您可以尝试在\之后保存更改,从而对
DbUpdateException
执行try catch

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
}
试试看
{
_context.Set().Add(实体);
_SaveChanges();
} 
捕获(DbUpdateException)
{
var isRaisedByUniqueIndexOrConstraint=new[]{“2601”,“2627”}.Contains(例如GetBaseException().Data[“HelpLink.EvtID”])?false;
如果(!isRaisedByUniqueIndexOrConstraint)
投
//无法抑制和\或处理尝试添加的重复记录
}
这取决于现有的索引\约束,因此您首先要在列上定义一个唯一的索引(以及使用数据注释的实体类型:
IndexAttribute


笔记
此答案\解决方案的一部分旨在从ADO.NET SqlClient Base Exception获取错误号,以进一步确定异常的范围和原因。在本例中,错误号“2601”、“2627”是硬编码的。

我认为可以确定您想要什么,但这个问题需要改进。添加有关
查找
不工作的更多信息:什么是
e
?如果是例外情况,请在您的问题中提供。另外,除非你已经尝试过,否则不要提出可能的答案。到那一点,你尝试过什么?好的,我只想添加对象例如student.add(new student{name=Marc}),然后我再添加一个student new student{name=Marc})ALERT->抱歉这个学生已经存在了最后我如何实现这个事件呢?另外,请举例说明你的用法,什么是
T
什么是
实体
;它是定义为实体还是继承自实体?当然,这实际上只是为了改进你的问题而做出的对称努力。实际答案是
Find
FirstOrDefault
Any
都将委托
Func
作为参数。我将尝试此方法_context.Set().Find((x)=>x==entity);我不能使用这个方法(x)=>x.Id==entity.Id,因为当我添加记录时,没有可以理解的Id值,我的意思是将
Id
作为典型用于唯一性\标识的属性的示例。无论您标识记录唯一性的方法是什么(否则它将是要添加的副本的原因),都应该是谓词的一部分。所以,这取决于数据。或者,没有理由在添加前检查这些字段是否唯一,对吗?啊。。。事实上我可能错了。。我链接了错误的文档。。我引用了
List.Find
,而不是
DbSet.Find
,它不使用谓词。。请更新您的问题,包括使用
Find
I更新我的答案时出现的异常或问题;我现在推荐
。任何
方法,并提供使用示例。我不想详细介绍Linq表达式,因为它涉及EntityFramework特性。这与问题或答案并不完全相关,关于技术和框架的使用,以及框架本身,还有很多需要了解的内容。
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
}