C# 通常使用LINQ查找项目属性值相等的任何项目

C# 通常使用LINQ查找项目属性值相等的任何项目,c#,linq,generics,reflection,C#,Linq,Generics,Reflection,我试图实现一个通用存储库模式,该模式实现IEnumerable中通用项的CRUD操作。我遇到了一个问题,就是一般性地查找一个可能已经在IEnumerable中的项。我需要以编程方式传递组成“键”或distinct记录的属性,然后使用LINQ对定义的属性执行Enumerable.Any()操作,以便查看对象是否已存在于IEnumerable中。这是到目前为止我的代码 //Generic Method public void AddItem(TEntity item) {

我试图实现一个通用存储库模式,该模式实现IEnumerable中通用项的CRUD操作。我遇到了一个问题,就是一般性地查找一个可能已经在IEnumerable中的项。我需要以编程方式传递组成“键”或distinct记录的属性,然后使用LINQ对定义的属性执行Enumerable.Any()操作,以便查看对象是否已存在于IEnumerable中。这是到目前为止我的代码

    //Generic Method
    public void AddItem(TEntity item)
    {
        var entities = GetAllItems().ToList(); //Method gets cached IEnumerable<TEntity>

        if(true)//Generically see if TEntity is already in the list based of defined properties
        {
            entities.Add(item);
        }

    }

    //Same function but non-generic
    private void AddItem(MyObject object)
    {
        var objects = GetAllItems().ToList(); //Method gets cached IEnumerable<MyObject>

        if(!objects.Any(a=> a.ID == MyObject.ID ))
        {
            objects.Add(object);
            _cache.AddReplaceCache(objects);
        }

    }
//泛型方法
公共无效附加项(有效项)
{
var entities=GetAllItems().ToList();//方法获取缓存的IEnumerable
if(true)//通常查看tenty是否已在基于已定义属性的列表中
{
实体。添加(项目);
}
}
//功能相同但非泛型
专用void附加项(MyObject对象)
{
var objects=GetAllItems().ToList();//方法获取缓存的IEnumerable
如果(!objects.Any(a=>a.ID==MyObject.ID))
{
对象。添加(对象);
_AddReplaceCache(对象);
}
}

注意:键可以是对象MyObject上的任何属性

如果我理解正确,您的问题是
tenty
没有属性
ID
。因此,让您的实体继承公共接口,例如ID列

public interface IObject
{
    int ID {get; set;}

    //define all other properties which are shared between your Entities.
}
public class MyObject : IObject
{
    public int ID {get; set;}

    //other properties.
}

public void AddItem(TEntity item): where TEntity:IObject
{
    var entities = GetAllItems().ToList(); //Method gets cached IEnumerable<TEntity>

    if(!objects.Any(a=> a.ID == item.ID ))//Generically see if TEntity is already in the list based of defined properties
    {
        entities.Add(item);
    }

}
公共接口对象
{
int ID{get;set;}
//定义实体之间共享的所有其他属性。
}
公共类MyObject:IOObject
{
公共int ID{get;set;}
//其他财产。
}
公共无效附加项(TEntity项):其中TEntity:IOObject
{
var entities=GetAllItems().ToList();//方法获取缓存的IEnumerable
if(!objects.Any(a=>a.ID==item.ID))//一般地查看TEntity是否已经在基于已定义属性的列表中
{
实体。添加(项目);
}
}

您可以使您的实体从公共接口继承:

public interface IEntity
{
    int ID { get; set; }
}
然后您可以像下面这样重新定义您的方法

public void AddItem<TEntity>(TEntity entity) where TEntity : IEntity
{
    // Now you can access entity.ID
}

看起来这应该是在上面一层执行的检查。我只是让复制密钥问题在db级别失败,因为它不应该到达存储库。同样,我不会使用泛型存储库。据我所知,每个实体都可以有一个由多个字段组成的复合键,这些字段将被传入并用于检查重复项。@stephen.vakil他说的是一些“键”,但我只是重新编写了他的代码来处理泛型。如果他有由多个字段组成的键,他需要在接口中定义它们,然后获取数据。这个过程应该是一样的,就像一个魔咒!非常感谢。
public void AddItem<TEntity>(TEntity entity, Func<TEntity, bool> predicate)
{
    var objects = GetAllItems().ToList();

    // You might need some logic in the predicate to check for null
    if(!objects.Any(a => predicate(a as TEntity))
    {
        objects.Add(entity);
        _cache.AddReplaceCache(objects);
    }

}
repository.AddItem(entity, e => e.ID == entity.ID && e.OtherProperty == entity.OtherProperty);