本文介绍了流利的NHibernate对象列表异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Fluent NHibernate的DAL,用于映射查询(作为字符串存储在db中)及其参数(存储在单独的表中).

I have a DAL using Fluent NHibernate for mapping a query (stored in db as strings) and their parameters (stored in a separate table).

当我尝试在服务层中使用此参数列表时,遇到了问题.

When I try to use this list of parameters in the service layer, I run into problems.

List<QueryParameter> lqp = (List<QueryParameter>)qry.parameters;

投掷


List<QueryParameter> lqp = qry.parameters.ToList<QueryParameter>();

投掷


List<QueryParameter> lqp = new List<QueryParameter>(qry.parameters);

投掷


IList<QueryParameter> lqp = (IList<QueryParameter>)qry.parameters;

投掷

public class Query
{
    public virtual int id { get; protected set; }
    public virtual string name { get; set; }
    public virtual string query { get; set; }
    public virtual IList<QueryParameter> parameters { get; set; }
    public virtual IList<Application> applicationsUsedIn { get; set; }

    public Query()
    {
        this.parameters = new List<QueryParameter>();
        this.applicationsUsedIn = new List<Application>();
    }

    public virtual void AddParameter(QueryParameter qp)
    {
        qp.query = this;
        this.parameters.Add(qp);
    }
}


public class QueryMap : ClassMap<Query>
{
    public QueryMap()
    {
        Table("dbo.Queries");
        Id(x => x.id);
        Map(x => x.name);
        Map(x => x.query);
        HasMany(x => x.parameters)
            .Cascade.All()
            .KeyColumn("qryid")
            .LazyLoad()
            ;
        HasManyToMany(x => x.applicationsUsedIn)
            .Table("dbo.ApplicationsQueries")
            .ParentKeyColumn("qryid")
            .ChildKeyColumn("appid")
            .Inverse()
            .LazyLoad()
            ;
    }
}


    public XmlNode runQuery(string appnname, string qryname, List<String> parms)
    {
        XmlNode xn = null;

        if ((null != appnname) && (appnname.Length > 0))
        {
            if ((null != qryname) && (qryname.Length > 0))
            {
                Query qry = md.getQuery(appnname, qryname);
                if (null != qry)
                {
                    if ((null != parms) && (parms.Count > 0)) //Passed parameters as List<String>
                    {
                        //These are the three lines I have tried
                        IList<QueryParameter> lqp = (IList<QueryParameter>)qry.parameters;
                        List<QueryParameter> lqp = qry.parameters.ToList<QueryParameter>();
                        List<QueryParameter> lqp = new List<QueryParameter>(qry.parameters);
    ...
    ...
    ...


已更新为QueryParameter类和映射.


Updated with QueryParameter class and map.

public class QueryParameter
{
    public virtual int id { get; set; }
    public virtual Query query { get; set; }
    public virtual string name { get; set; }
    public virtual MOLEDataTypes type { get; set; }
    public virtual int order { get; set; }

    public QueryParameter()
    {
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        var t = obj as QueryParameter;
        if (t == null)
            return false;
        if (query == t.query && name == t.name)
            return true;
        return false;
    }

    public override int GetHashCode()
    {
        return (query.id + "|" + name).GetHashCode();
    }
}


public class QueryParametersMap : ClassMap<QueryParameter>
{
    public QueryParametersMap()
    {
        Table("dbo.QueryParameters");
        Id(x => x.id);
        References(x => x.query).Column("qryid").Not.Insert();
        Map(x => x.name);
        Map(x => x.type).CustomType<MOLEDataTypes>();
        Map(x => x.order).Column("ordr");
    }
}

更多代码

    public Query getQuery(string appname, string qryname)
    {
        Query retq = null;

        using (ISessionFactory isf = getSessionFactory())
        {
            using (var sess = isf.OpenSession())
            {
                using (var tran = sess.Transaction)
                {
                    try
                    {
                        tran.Begin();
                        ...
                        USING session
                        ...
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                        sess.Close();
                        lws.logMessage(AppName, "getQuery", ex.ToString(), MessageType.Error, MessageLevel.Error);
                    }
                }
            }
        }

        return (retq);
    }

任何提示或建议,我们将不胜感激.

Any hints or suggestions you might have would be greatly appreciated.

谢谢

布鲁斯.

推荐答案

问题是您关闭了getQuery中的会话,然后要求您的Query对象的参数列表,NHibernate尝试加载该对象并由于缺少会话而失败.为了解决您的问题,您需要确保您的会话在整个请求中都处于打开状态,或者至少在所有业务交易完成之前保持打开状态.

The problem is that you close the session in getQuery, and then ask for the list of parameters for your Query object, which NHibernate tries to load and fails due to the absence of a session. To solve your problem, you need to ensure that your session is open throughout the request, or at least remains open until all business transactions have completed.

我建议您采用每次请求会话的方法.每当有网络请求时打开一个会话,并在会话结束时关闭它.使用Global.asax文件可以轻松实现此目的,您可以阅读此处.

I would suggest that you take a session-per-request approach. Open a session whenever there's a web request, and close it when the session ends. This can be achieved easily by using the Global.asax file, which you can read about here.

public class Global : System.Web.HttpApplication
{
    public static ISessionFactory SessionFactory { get; private set; }

    protected void Application_Start(object sender, EventArgs e)
    {
        // Create a session factory when the application starts.
        // Session factories are expensive to create, and therefore you should create one and use it throughout your application.
        SessionFactory = Fluently.Configure()
                                 .Database(
                                    SQLiteConfiguration.Standard
                                        .UsingFile("firstProject.db")
                                 )
                                 .BuildSessionFactory();
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        // Create a session per request.
        var session = SessionFactory.OpenSession();
        CurrentSessionContext.Bind(session);
    }

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        // Close the session at the end of every request
        var session = CurrentSessionContext.Unbind(SessionFactory);
        session.Dispose();
    }

    protected void Application_End(object sender, EventArgs e)
    {
        // Close the session factory at the end of the application.
        if (SessionFactory != null)
            SessionFactory.Dispose();
    }
}

在上面的示例中,在应用程序启动时会创建会话工厂,因此建议这样做,因为创建会话工厂的成本很高.然后,每个请求都会创建一个会话,并在最后放置会话.通过使用这种方法,由于所有操作都是自动完成的,因此您可以节省很多工作.

In the example above, a session factory is created when the application starts, which is recommended because it is costly to create a session factory. Then, a session is created every request, and disposed at the end. By using this approach, you save yourself a lot of work since everything is done automatically.

然后,要在代码中使用会话,您只需调用GetCurrentSession(),如下所示:

Then, to use a session in your code, you would just need to call GetCurrentSession(), like so:

var session = Global.SessionFactory.GetCurrentSession();

我希望这对您有所帮助,并祝您好运NHibernate.我建议您考虑阅读 NHibernate 3.0食谱,以便更好地理解NHibernate的.

I hope that helps, and best of luck fiddling with NHibernate. I would suggest you to consider reading the NHibernate 3.0 Cookbook for a better understanding of NHibernate.

这篇关于流利的NHibernate对象列表异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 02:51