2014-04-07 7 views
5

में मुझे स्ट्रिंग संग्रह का चयन करने में समस्या है और इसे निम्न छोटे उदाहरण के साथ पुन: उत्पन्न किया गया है।लिंकक का उपयोग कर स्ट्रिंग संग्रह पर एनएचबर्ननेट क्वेरीिंग या तो त्रुटि या खाली संग्रह

को देखते हुए निम्नलिखित एसक्यूएल:

CREATE TABLE [Post] (
    [Id] INT  IDENTITY NOT NULL, 
    [Name] NVARCHAR(20) NOT NULL, 
    CONSTRAINT [PK_Post] PRIMARY KEY CLUSTERED ([Id]) 
) 
CREATE TABLE [Category] (
    [Id] INT  IDENTITY NOT NULL, 
    [PostId] INT NOT NULL, 
    [Name] NVARCHAR(20) NOT NULL, 
    CONSTRAINT [FK_Category_Post] FOREIGN KEY ([PostId]) REFERENCES [Post]([Id]) 
) 
INSERT INTO [Post] ([Name]) VALUES ('Post 1') 
INSERT INTO [Category] ([PostId], [Name]) VALUES (1, 'Alpha') 

और कोड (मैं LINQPad प्रयुक्त):

void Main() 
{ 
    using (var sessionFactory = Fluently.Configure() 
     .Database(MsSqlConfiguration.MsSql2008.Dialect<MsSql2012Dialect>().ConnectionString(@"Data Source=(localdb)\Projects;Initial Catalog=NhTest;")) 
     .Mappings(x => { 
      x.FluentMappings.Add(typeof(PostMap)); 
     }) 
     .BuildSessionFactory()) 
    using (var session = sessionFactory.OpenSession()) 
    { 
     var post = session.Get<Post>(1); 
     Debug.Assert(post.Categories.First() == "Alpha"); 

     try { 
      var second = session.Query<Post>() 
       .Where(x => x.Id == 1) 
       .Select(x => new { 
        x.Categories, 
        x.Name, 
       }) 
       .Single(); 
     } 
     catch (Exception ex) { 
      Debug.Fail(ex.ToString()); 
     } 

     var third = session.Query<Post>() 
      .Where(x => x.Id == 1) 
      .Select(x => new { 
       x.Categories, 
       x.Name, 
      }) 
      .ToList().First(); 

     Debug.Assert(third.Categories.Count() == 1, "Category count was " + third.Categories.Count()); 
    } 
} 

// Define other methods and classes here 
class Post 
{ 
    public virtual int Id { get; protected set; } 
    public virtual string Name { get; protected set; } 
    public virtual IList<string> Categories { get; protected set; } 
} 

class PostMap : ClassMap<Post> 
{ 
    public PostMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Name); 

     HasMany(x => x.Categories) 
      .Table("Category") 
      .Element("Name") 
      .KeyColumn("PostId"); 
    } 
} 

पहले ज़ोर गुजरता है और इस, मेरे मन में, पर श्रेणियों में से मेरी मानचित्रण सत्यापित करता है पोस्ट।

कोशिश ब्लॉक में क्वेरी एक अपवाद

'System.Linq.EnumerableQuery`1[System.Collections.Generic.IList`1[System.String]]' cannot be converted to type 'System.Linq.IQueryable`1[System.Object[]] 

तो मैं यह आप कोड में देख 3 प्रयास, .ToList().First() बुला लिए बदल दिया है फेंकता है। यह क्वेरी कोई अपवाद नहीं फेंकती है लेकिन श्रेणियों की सूची खाली हो जाती है।

क्या मैं कुछ गलत कर रहा हूं? क्या यहां उपयोग करने के लिए एक बेहतर मैपिंग तकनीक है? या क्या मेरी क्वेरी काम करने के लिए कामकाज हैं?

उत्तर

5

यह NHibernate में एक बग था। यह संख्यात्मक प्रकार पैरामीटर के लिए क्लास मैपिंग डेटा प्राप्त करने का प्रयास करेगा। मैप किए गए वर्ग की गणना करने पर यह पूरी तरह से काम करता है। इस उदाहरण में, हालांकि, संख्यात्मक प्रकार पैरामीटर स्ट्रिंग है। स्ट्रिंग में क्लास मैप नहीं है और इसलिए यह क्वेरी में एक निरंतर स्थिरता को प्रतिस्थापित कर रहा था जिसके बाद बाद में समस्याएं उत्पन्न हुईं।

आगे इसे दर्शाने के लिए, इस उदाहरण के लिए SQL क्वेरी होगा:

SELECT c.Name, p.Id, p.Name FROM Post p LEFT JOIN Category c ON p.Id = c.PostId WHERE p.Id = 1 

यह बहुत की तरह डेटा वापसी होगी:

c.Name | p.Id | p.Name 
-------------------------- 
Cat 1 | 1  | Post A 
Cat 2 | 1  | Post A 

NHibernate तो, स्मृति में, एक समूह द्वारा प्रदर्शन करेंगे पी.आईडी के प्रत्येक अद्वितीय मूल्य के लिए श्रेणियों की एक सूची बनाने के लिए, शून्य जांच सहित ऑपरेशन। ऑपरेशन द्वारा समूह कॉलम इंडेक्स का उपयोग करके किया जाता है।

यही हो रहा है। बग, आपरेशन द्वारा पैदा कर रहा था परिणाम तब्दील किया जा करने के लिए, समूह से पहले में:

NULL | Cat 1 | 1  | Post A 
NULL | Cat 2 | 1  | Post A 

NHibernate फिर परिणाम जहां स्तंभ 0 अशक्त था, जिसका अर्थ उनमें से कोई भी जीवित रहने को छानने था।

ठीक युक्त पुल अनुरोध यहाँ है: https://github.com/nhibernate/nhibernate-core/pull/262

1

आप CategoryMap, Category इकाई बनाने और बदलने के लिए कर सकते हैं:

public virtual IList<Category> Categories { get; protected set; } 

मैं मानते हुए कर रहा हूँ nhibernate क्वेरी करने सीमा के लिए एक LINQ है।

+0

मैं वास्तव में मेरे डोमेन बेहतर सूट स्ट्रिंग की एक सूची होने के रूप में एक नया श्रेणी वर्ग बनाने से बचना चाहते थे। मैंने QueryOver के साथ यह भी कोशिश की है और एक ही त्रुटि प्राप्त करें। – Matt

1

कोशिश बदलते

var second = session.Query<Post>() 
    .Where(x => x.Id == 1) 
    .Select(x => new { 
     x.Categories, 
     x.Name, 
    }) 
    .Single(); 

ToList().Single() बजाय Single() करना।

मैंने पहले इस मुद्दे को देखा है, समस्या यह है कि क्वेरी कई पंक्तियों को वापस कर देगी जिन्हें बाद में एक अनाम प्रकार में घुमाया जाता है। क्वेरी विफल हो जाती है क्योंकि मध्यवर्ती परिणामों में एक पंक्ति के बजाय एकाधिक पंक्तियां होती हैं।

+0

मैंने अपने नमूना कोड में तीसरी क्वेरी में ऐसा किया है लेकिन मुझे गलत परिणाम मिलते हैं। – Matt

+0

पूरी बात पढ़ने के बिना उस पर कूदने के लिए खेद है। मैंने लगभग समान क्वेरी बनाई और यह अपेक्षित परिणाम लौटा। क्या आपने एसक्यूएल को डेटाबेस में भेजा है? मैं देखता हूं कि आप स्थानीय डेटाबेस का उपयोग कर रहे हैं, मेरा अनुमान है कि आप सही डेटाबेस को मार नहीं रहे हैं। –

+0

मैंने क्वेरी हाँ प्रोफाइल किया है, और यह सही मानों का चयन करता है। मैं इस समय एनएच स्रोत कोड के माध्यम से कदम उठा रहा हूं, ऐसा लगता है कि यह गलत क्लाइंट-साइड ट्रांसफॉर्म उत्पन्न कर रहा है। – Matt

संबंधित मुद्दे