c# - प्राथमिक के द्वारा इकाई फ़्रेमवर्क फ़िल्टर




entity-framework find (2)

मैं एक सामान्य क्रूड सेवा लिख ​​रहा हूँ, मैं गुणों को शामिल करने के लिए एक वैकल्पिक आभासी पद्धति के साथ Get विधि को लागू करने का प्रयास कर रहा हूं हालांकि मुझे कुछ परेशानी हो रही है क्योंकि FindAsync केवल एक DbSet पर घोषित किया गया है:

public async virtual Task<TDTO> Get(object[] id)
{
     // I want to do something like this
     var entity = await this.ApplyGetIncludes(this.GetEntityDBSet()).FindAsync(id)
     return this.AdaptToDTO(entity);
}

protected virtual DbSet<TEntity> GetEntityDBSet()
{
    return this._context.Set<TEntity>();
}

protected virtual IQueryable<TEntity> ApplyGetIncludes(IQueryable<TEntity> queryable)
{
    return queryable;
}

मैं ऐसा कुछ करना चाहता हूं जैसा ऊपर दर्शाया गया है:

var entity = await this.ApplyGetIncludes(this.GetEntityDBSet()).FindAsync(id)

लेकिन मुझे पता है कि यह काम नहीं करेगा क्योंकि हमें डीबी सेट की ज़रूरत है, इसलिए मैं ऐसा कुछ करने के लिए सेट करूँगा:

var entity = await this.ApplyGetIncludes(this.GetEntityDBSet().FilterByPK(id))
                      .FirstOrDefaultAsync();

क्या किसी को पता है कि मैं DbSet से प्राथमिक कुंजी के द्वारा कैसे फ़िल्टर कर सकता DbSet ?


आप प्रश्न थोड़ा मुश्किल लगता है मेरे विचार में, आप सभी लक्ष्य को प्राप्त करना असंभव है, प्राथमिक तालिका के आधार पर सभी टेबल्स में फ़िल्टर करने के लिए एक सामान्य पद्धति का उद्देश्य। आपके ऊपर दिए गए कोड में आईडी का मतलब तालिका (डीबीएसटी) की कुंजी है। और आपको अलग-अलग तालिका क्वेरी के अनुसार आईडी को अलग तरह से व्यवहार करना होगा। इस तरह, मुझे लगता है कि आप डेटा प्राप्त करने के लिए निम्नलिखित के रूप में एक सार पद्धति का बेहतर उपयोग कर रहे हैं

public async abstract Task<TDTO> Get(object[] id)
{
   //I want to do something like this
   var entity = await this.ApplyGetIncludes(this.GetEntityDBSet()).FindAsync(id)
   return this.AdaptToDTO(entity);
}

आपको कंक्रीट तालिकाओं के अनुसार अपने प्राप्त विधि को लागू करना होगा (जबकि प्रत्येक तालिका में आमतौर पर अलग-अलग प्राथमिक कुंजी होती है)


यह संभव है, लेकिन प्राथमिक कुंजी का वर्णन मेटाडेटा प्राप्त करने के लिए विधि को DbContext तक पहुंच की आवश्यकता है। तो यह उस मेटाडेटा और पारित मूल्यों के आधार पर लैम्ब्डा अभिव्यक्ति को गतिशील रूप से परिभाषित कर सकता है।

पहले हमें प्राथमिक विधि के बारे में जानकारी एकत्र करने वाली विधि की आवश्यकता है।

ईएफ कोर के लिए यह आसान है:

static IReadOnlyList<IProperty> GetPrimaryKeyProperties(DbContext dbContext, Type clrEntityType)
{
    return dbContext.Model.FindEntityType(clrEntityType).FindPrimaryKey().Properties;
}

ईएफ 6 के लिए यह थोड़ा और अधिक जटिल है, लेकिन अभी भी संभव है:

struct KeyPropertyInfo
{
    public string Name;
    public Type ClrType;
}

public static IReadOnlyList<KeyPropertyInfo> GetPrimaryKeyProperties(DbContext dbContext, Type clrEntityType)
{
    var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
    var metadata = objectContext.MetadataWorkspace;
    var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
    var entityType = metadata.GetItems<EntityType>(DataSpace.OSpace)
        .Single(e => objectItemCollection.GetClrType(e) == clrEntityType);
    return entityType.KeyProperties
        .Select(p => new KeyPropertyInfo
        {
            Name = p.Name,
            ClrType = p.PrimitiveType.ClrEquivalentType
        })
        .ToList();
}

अब विधेय को बनाने का तरीका इस तरह है:

static Expression<Func<T, bool>> BuildKeyPredicate<T>(DbContext dbContext, object[] id)
{
    var keyProperties = GetPrimaryKeyProperties(dbContext, typeof(T));
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = keyProperties
        // e => e.PK[i] == id[i]
        .Select((p, i) => Expression.Equal(
            Expression.Property(parameter, p.Name),
            Expression.Convert(
                Expression.PropertyOrField(Expression.Constant(new { id = id[i] }), "id"),
                p.ClrType)))
        .Aggregate(Expression.AndAlso);
    return Expression.Lambda<Func<T, bool>>(body, parameter);
}

यहां मुश्किल भाग यह है कि ईएफ पैरामीटर वाले क्वेरी का उपयोग कैसे करें। यदि हम बस Expression.Constant(id[i]) प्रयोग करते हैं। Expression.Constant(id[i]) , उत्पन्न एसक्यूएल पैरामीटर के बजाए स्थिर मानों का उपयोग करेगा तो चाल मूल्य (मूल रूप से समाल करना बंद करना) धारण अस्थायी गुमनाम प्रकार की निरंतर अभिव्यक्ति के सदस्य पहुंच अभिव्यक्ति (यानी संपत्ति या क्षेत्र) का उपयोग करने के लिए है।

उपरोक्त विधि से एक बार जब आप प्राप्त करते हैं, तो आप इसका उपयोग FirstOrDefaultAsync या किसी अन्य फ़िल्टरिंग विधि के लिए कर सकते हैं।





find