【问题标题】:Self-Referencing HasMany Relationship in Fluent NHibernate and MVC3Fluent NHibernate 和 MVC3 中的自引用 HasMany 关系
【发布时间】:2011-06-26 00:38:34
【问题描述】:

我有一个用于字典/同义词库的 Word 模型:

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);

【问题讨论】:

    标签: c# fluent-nhibernate asp.net-mvc-3 has-many


    【解决方案1】:

    尝试使用标识列 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);
    

    更新:

    这是一个完整的工作示例(使用 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();
        }
    }
    

    【讨论】:

    • 不,还是同样的问题。
    • @Darin,我在运行该程序时遇到错误:无法从 NHibernate.Driver.SQLite20Driver 创建驱动程序。无论哪种方式,我所做的几乎所有事情都与您在我的实际程序中一样,它仍然是混合收藏。当我实际从文件构建字典时,我打印出同义词/反义词,它们是正确的。
    • @Wesley Tansey,在我的示例中,我使用的是 SQLite,因此请确保您引用了 System.Data.SQLite.dll 程序集。
    • 我安装了 SQLite 并引用了它,但我仍然得到同样的错误。
    • @Wesley Tansey,你是在 .NET 4.0 上运行它吗?您还在 x64 操作系统上运行它吗?有一些注意事项:stackoverflow.com/questions/2605490/system-data-sqlite-net-4/…
    猜你喜欢
    • 1970-01-01
    • 2011-02-27
    • 2012-10-19
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 2011-12-20
    • 2011-04-15
    • 2013-05-20
    相关资源
    最近更新 更多