2011-02-12 50 views
1

我有一本字典/詞典的詞模型:自引用的hasMany關係流利的NHibernate和MVC3

public class Word 
{ 
    public virtual string Text { get; set; } 
    public virtual IList<Word> Synonyms { get; set; } 
    public virtual IList<Word> Antonyms { get; set; } 
} 

每個單詞有很多同義詞和反義詞。 Word有一個映射:

public class WordMapping : ClassMap<Word> 
{ 
    Id(x => x.Text); 
    HasMany(x => x.Synonyms); 
    HasMany(x => x.Antonyms); 
} 

在我的控制,我有一個字一個簡單的查找方法:

public ActionResult Word(string word) 
{ 
    using (var session = MvcApplication.SessionFactory.OpenSession()) 
    { 
     using (var transaction = session.BeginTransaction()) 
     { 
      var result = session.QueryOver<Word>() 
           .Where(w => w.Text == word) 
           .SingleOrDefault(); 

      if(result == null) 
       RedirectToAction("InvalidWord"); 

      ViewBag.Synonyms = result.Synonyms.Select(t => t.Text); 
      ViewBag.Antonyms = result.Antonyms.Select(t => t.Text); 

      return View(result); 
     } 
    } 
} 

當我打印出在我看來,ViewBag集合,它們都是相同的。它們是一些看似任意選擇兩個包的元素,但不包括整個包。

更新:下面是我將代碼提交給數據庫的代碼,如果有幫助的話。在提交後打印words時,所有同義詞都是正確的。

List<Word> words; 
... 
using (var session = MvcApplication.SessionFactory.OpenSession()) 
{ 
    // populate the database 
    using (var transaction = session.BeginTransaction()) 
    { 
     foreach (var word in words) 
      session.Save(word); 

     transaction.Commit(); 
    } 
} 

PrintWords(words); 

回答

3

嘗試使用標識列Id代替Text屬性:

public class Word 
{ 
    public virtual int Id { get; set; } 
    public virtual string Text { get; set; } 
    public virtual IList<Word> Synonyms { get; set; } 
    public virtual IList<Word> Antonyms { get; set; } 
} 

然後:

Id(x => x.Id); 
Map(x => x.Text); 
HasMany(x => x.Synonyms); 
HasMany(x => x.Antonyms); 

UPDATE:

這裏是一個完整的工作示例(使用SQLite和控制檯應用程序來簡化,但類似的技術可以應用於您的Web應用程序):

// Domain layer 
public class Word 
{ 
    public virtual int Id { get; set; } 
    public virtual string Text { get; set; } 
    public virtual IList<Word> Synonyms { get; set; } 
    public virtual IList<Word> Antonyms { get; set; } 
} 

// Mapping layer 
public class WordMapping : ClassMap<Word> 
{ 
    public WordMapping() 
    { 
     Id(x => x.Id).UnsavedValue(0); 
     Map(x => x.Text); 
     HasMany(x => x.Synonyms).Cascade.AllDeleteOrphan(); 
     HasMany(x => x.Antonyms).Cascade.AllDeleteOrphan(); 
    } 
} 

// Data access layer 
class Program : InMemoryDatabase 
{ 
    static void Main(string[] args) 
    { 
     using (var p = new Program()) 
     { 
      // save some dummy data into the database 
      var word = new Word 
      { 
       Text = "myword", 
       Synonyms = new[] 
       { 
        new Word { Text = "synonym 1" }, 
        new Word { Text = "synonym 2" }, 
       }.ToList(), 
       Antonyms = new[] 
       { 
        new Word { Text = "antonym 1" }, 
       }.ToList() 
      }; 
      using (var tx = p.Session.BeginTransaction()) 
      { 
       p.Session.Save(word); 
       tx.Commit(); 
      } 

      // and now let's query the database 
      using (var tx = p.Session.BeginTransaction()) 
      { 
       var result = p.Session 
           .QueryOver<Word>() 
           .Where(w => w.Text == "myword") 
           .SingleOrDefault(); 

       var synonyms = result.Synonyms.Select(t => t.Text).ToArray(); 
       Console.WriteLine("-- Synonyms --"); 
       foreach (var item in synonyms) 
       { 
        Console.WriteLine(item); 
       } 

       var antonyms = result.Antonyms.Select(t => t.Text).ToArray(); 
       Console.WriteLine("-- Antonyms --"); 
       foreach (var item in antonyms) 
       { 
        Console.WriteLine(item); 
       } 
      } 
     } 
    } 
} 

public abstract class InMemoryDatabase : IDisposable 
{ 
    private static Configuration _configuration; 
    private static ISessionFactory _sessionFactory; 

    protected ISession Session { get; set; } 

    protected InMemoryDatabase() 
    { 
     _sessionFactory = CreateSessionFactory(); 
     Session = _sessionFactory.OpenSession(); 
     BuildSchema(Session); 
    } 
    private static ISessionFactory CreateSessionFactory() 
    { 
     return Fluently.Configure() 
      .Database(SQLiteConfiguration.Standard.InMemory().ShowSql()) 
      .Mappings(M => M.FluentMappings.AddFromAssemblyOf<WordMapping>()) 
      .ExposeConfiguration(Cfg => _configuration = Cfg) 
      .BuildSessionFactory(); 
    } 

    private static void BuildSchema(ISession Session) 
    { 
     SchemaExport export = new SchemaExport(_configuration); 
     export.Execute(true, true, false, Session.Connection, null); 
    } 

    public void Dispose() 
    { 
     Session.Dispose(); 
    } 
} 
+0

不,仍然是同樣的問題。 – 2011-02-12 09:46:08