FNH和NH的新手。
我想优化OneToMany映射的查询。我实际上只想检索Segment = 0的许多地方之一.PlantID,AreaID,CellID,DeviceID,StartDateTime组成Data的复合主键。将Segment添加到DataMore1和DataMore2的组合键。
事件最多可以记录400个数据点......具体取决于他们选择的选项。 因此,我们选择将数据存储在单独的表中,以便在x天或数月后清除不需要的数据。
目标是通过FluentNHibernate做这样的事情。
SELECT Data.PlantID, Data.AreaID, Data.CellID, Data.DeviceID, Data.StartDateTime, Data.DataPoint01, DataMore1.Segment, DataMore1.DataPoint101,
DataMore2.DataPoint201
FROM Data
LEFT OUTER JOIN
DataMore1 ON Data.PlantID = DataMore1.PlantID AND Data.AreaID = DataMore1.AreaID AND Data.CellID = DataMore1.CellID AND
Data.DeviceID = DataMore1.DeviceID AND Data.StartDateTime = DataMore1.StartDateTime AND **DataMore1.Segment = 0**
LEFT OUTER JOIN
DataMore2 ON Data.PlantID = DataMore2.PlantID AND Data.AreaID = DataMore2.AreaID AND Data.CellID = DataMore2.CellID AND
Data.DeviceID = DataMore2.DeviceID AND Data.StartDateTime = DataMore2.StartDateTime AND **DataMore2.Segment = 0**
模型
public class Data
{
public virtual int PlantID { get; set; }
public virtual int AreaID { get; set; }
public virtual int CellID { get; set; }
public virtual int DeviceID { get; set; }
public virtual DateTime StartDateTime { get; set; }
public virtual float DataPoint01 { get; set; }
public virtual float DataPoint02 { get; set; }
public virtual float DataPoint99 { get; set; }
public virtual IEnumerable<DataMore1> DataMore1 { get; set; }
public virtual IEnumerable<DataMore2> DataMore2 { get; set; }
}
public class DataMore1
{
public virtual int PlantID { get; set; }
public virtual int AreaID { get; set; }
public virtual int CellID { get; set; }
public virtual int DeviceID { get; set; }
public virtual DateTime StartDateTime { get; set; }
public virtual byte Segment { get; set; }
public virtual float DataPoint101 { get; set; }
public virtual float DataPoint102 { get; set; }
public virtual float DataPoint199 { get; set;}
}
public class DataMore2
{
public virtual int PlantID { get; set; }
public virtual int AreaID { get; set; }
public virtual int CellID { get; set; }
public virtual int DeviceID { get; set; }
public virtual DateTime StartDateTime { get; set; }
public virtual byte Segment { get; set; }
public virtual float DataPoint201 { get; set; }
public virtual float DataPoint202 { get; set; }
public virtual float DataPoint299 { get; set; }
}
和MAPPINGS
public DataMap()
{
Table("Data");
CompositeId()
.KeyProperty(e => e.PlantID)
.KeyProperty(e => e.AreaID)
.KeyProperty(e => e.CellID)
.KeyProperty(e => e.DeviceID)
.KeyProperty(e => e.StartDateTime);
Map(e => e.DataPoint01);
Map(e => e.DataPoint02);
Map(e => e.DataPoint99);
HasMany(e => e.DataMore1)
.KeyColumns.Add("PlantID")
.KeyColumns.Add("AreaID")
.KeyColumns.Add("CellID")
.KeyColumns.Add("DeviceID")
.KeyColumns.Add("StartDateTime")
.Cascade.All().Inverse();
HasMany(e => e.DataMore2)
.KeyColumns.Add("PlantID")
.KeyColumns.Add("AreaID")
.KeyColumns.Add("CellID")
.KeyColumns.Add("DeviceID")
.KeyColumns.Add("StartDateTime")
.Cascade.All().Inverse();
}
public DataMore1Map()
{
Table("DataMore1");
CompositeId()
.KeyProperty(e => e.PlantID)
.KeyProperty(e => e.AreaID)
.KeyProperty(e => e.CellID)
.KeyProperty(e => e.DeviceID)
.KeyProperty(e => e.StartDateTime)
.KeyProperty(e => e.Segment);
Map(e => e.DataPoint101);
Map(e => e.DataPoint102);
Map(e => e.DataPoint199);
}
public DataMore2Map()
{
Table("DataMore2");
CompositeId()
.KeyProperty(e => e.PlantID)
.KeyProperty(e => e.AreaID)
.KeyProperty(e => e.CellID)
.KeyProperty(e => e.DeviceID)
.KeyProperty(e => e.StartDateTime)
.KeyProperty(e => e.Segment);
Map(e => e.DataPoint201);
Map(e => e.DataPoint202);
Map(e => e.DataPoint299);
}
答案 0 :(得分:1)
那么,这是一个查询问题?
由于你是NH的新手,我给出的答案比要求的要宽一些。前两个课程应该自己回答你的问题。
public class DataQuery : AbstractQueryObject<IList<DataQueryResult>>
{
public override IList<DataQueryResult> GetResult()
{
DataMore1 dm1 = null;
DataMore2 dm2 = null;
var list =
this.Session.QueryOver<Data>()
.JoinAlias(data => data.DataMore1, () => dm1, NHibernate.SqlCommand.JoinType.LeftOuterJoin, Expression.Eq("Segment", 0))
.JoinAlias(data => data.DataMore2, () => dm2, NHibernate.SqlCommand.JoinType.LeftOuterJoin, Expression.Eq("Segment", 0))
.Select(p =>
new DataQueryResult
{
PlantID = p.PlantID,
AreaID = p.AreaID,
CellID = p.CellID,
DeviceID = p.DeviceID,
StartDateTime = p.StartDateTime,
DataPoint01 = p.DataPoint01,
DataMore1Segment = dm1.Segment,
DataMore1DataPoint101 = dm1.DataPoint101,
DataMore2Segment = dm2.Segment,
DataMore2DataPoint201 = dm2.DataPoint201
})
.List<DataQueryResult>();
return list;
}
}
public class DataQueryResult
{
internal DataQueryResult() { }
public int PlantID { get; internal set; }
public int AreaID { get; internal set; }
public int CellID { get; internal set; }
public int DeviceID { get; internal set; }
public DateTime StartDateTime { get; internal set; }
public float DataPoint01 { get; internal set; }
public byte? DataMore1Segment { get; internal set; }
public float? DataMore1DataPoint101 { get; internal set; }
public byte? DataMore2Segment { get; internal set; }
public float? DataMore2DataPoint201 { get; internal set; }
}
public abstract class AbstractQueryObject<TResult> : IQueryObject<TResult>
{
protected ISession Session;
public void Configure(object parameter)
{
/*obviously this NH query object implementation has to be provided with an ISession before it executes.
for that purpose I have an generic repository which holds an ISession and exposes the method
public interface IRepository { .. TResult ExecuteQuery<TResult>(IQueryObject<TResult> query); .. }
and has the usual Save<T>/Delete<T> methods.
obviously, to get the results you use: var data = repository.ExecuteQuery(new DataQuery());
i like this pattern a lot, so forgive my promotion :)
now, one repo instance keeps alive its session, so all entities from it are from the same isession.
when you dispose the repo, you kill the session. if you use DI in your classes, the repo instance is injected.
very perky is that your classes depend on the iqo and irepo ifcs which means you can swap them for EF which sometimes we do:)
easy unit testing.. etc.. */
if (!(parameter is ISession))
throw new ArgumentException("Argument of wrong type.");
this.Session = parameter as ISession;
}
public abstract TResult GetResult();
}
public interface IQueryObject<TResult>
{
void Configure(object parameter);
TResult GetResult();
}
答案 1 :(得分:0)
对接受的答案的这种修改使我得到了我想去的地方。结果是一个select语句,它返回我需要的东西......
var list = session.QueryOver<Data>()
.JoinAlias(data => data.DataMore1, () => dm1, NHibernate.SqlCommand.JoinType.LeftOuterJoin, Expression.Eq("Segment", (byte)0))
.JoinAlias(data => data.DataMore2, () => dm2, NHibernate.SqlCommand.JoinType.LeftOuterJoin, Expression.Eq("Segment", (byte)0))
.List<Data>()
});