【问题标题】:How to apply the same query to different entities?如何将相同的查询应用于不同的实体?
【发布时间】:2013-01-24 14:51:18
【问题描述】:

所以,我开始使用 EF,并且正在开发一个使用它作为 ORM 的应用程序。问题是我没有太多时间深入研究文档(我计划在适当的时候)而且我有点迷失在某些事情上。例如,我有这两个查询:

public static int GetNextPadlockNumber()
        {
            LockersDBEntities1 entities = new LockersDBEntities1();
            var query = (from p in entities.PadLocks select p.PadlockNumber).DefaultIfEmpty(0).Max();
            return (int)query + 1;
        }

        public static Data.PadLock GetPadLockByNumber(int number)
        {
            Data.LockersDBEntities1 entities = new LockersDBEntities1();
            var query = (from p in entities.PadLocks where p.PadlockNumber == number select p).FirstOrDefault();
            return query;
        }

public static int GetNextLockerNumber()
        {
            LockersDBEntities1 entities = new LockersDBEntities1();
            var query = (from l in entities.Lockers select l.LockerNumber).DefaultIfEmpty(0).Max();
            return (int)query+1;
        }

        public static Data.Locker GetLockerByNumber(int number)
        {
            Data.LockersDBEntities1 entities = new LockersDBEntities1();
            var query = (from l in entities.Lockers where l.LockerNumber == number select l).FirstOrDefault();
            return query;
        }

问题是它们是完全相同的查询。没有任何方法可以做到这一点而不必指定我想要一个储物柜或挂锁吗?先谢谢各位大侠了。

【问题讨论】:

    标签: c# .net visual-studio-2010 entity-framework


    【解决方案1】:

    您可以使用 LockerNumberPadlockNumber 作为身份自动增量字段,因为您正在这样做,然后将它们命名为相同(例如 Id)。

    这样就不再需要“获取下一个储物柜号码”,因为插入的每个新实体都将获得下一个可用号码,并且使用存储库模式,您可以将这些方法作为基本存储库类中的常用方法像这样:

    public IEntity GetEntityById(int number)
    {
       return ObjectSet.Single(x => x.Id == number);
    }
    

    【讨论】:

    • 我不能让它们自动增量。这将使用户无法创建已分配号码的现有储物柜和挂锁。
    【解决方案2】:

    EF 的一大优点是您可以做类似的事情。这不是微不足道的,需要反复试验,但您可以抽象出很多数据库复杂性。

    现在,假设LockersDBEntities1DbContext,你可以这样:

    public static class LockersDBEntities1Extensions
    {
       public static int GetNextNumber<T>(
            this LockersDBEntities1 context, 
            Expression<Func<T, int>> getNumberExpression)
       {
         var query = (from item in context.Set<T> 
                      select getNumberExpression(item))
                     .DefaultIfEmpty(0)
                     .Max();
         return (int)query + 1;
        }
    }
    

    并像这样使用它:

    int nextPadlockNumber = new LockersDBEntities1()
                                        .GetNextNumber<Padlock>(p => p.PadlockNumber)
    

    int nextPadlockNumber = new LockersDBEntities1()
                                        .GetNextNumber<Locker>(l => l.LockerNumber)
    

    getNumberExpression 表达式是必需的,因为没有通用的方法可以访问所有实体的数字。这可能是过度设计,但如果这是一个问题,我会这样做:

    //this should be a better name, to reflect the real scenarion
    interface ILockNumberProvider 
    {
       int Number {get; }
    }
    

    并在LockerPadlock 和其他需要提供锁号的类上实现该接口。然后,在上面的方法中,表达式可以省略,而可以使用泛型约束,比如:

    public static class LockersDBEntities1Extensions
    {
       public static int GetNextNumber<T>(this LockersDBEntities1 context)
                         where T:ILockNumberProvider 
       {
         var query = (from item in context.Set<T> 
                      select item.Number)
                     .DefaultIfEmpty(0)
                     .Max();
         return (int)query + 1;
        }
    }
    

    【讨论】:

    • 这实际上非常接近我想要的,虽然有点复杂。问题是我使用的是实体框架 4,它没有 DBContext.Set() 方法。但是谢谢,我正朝着正确的方向前进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    相关资源
    最近更新 更多