在实体框架中使用部分类与自定义属性 [英] Using partial-classes in Entity Framework with custom properties
问题描述
这是设置:
TimeSheet表 - 这存储员工的小时
- TimeSheetID(auto,int,PK)
- EntryDate(DateTime)
- 小时(int)
- EmployeeID(int)
EmployeeHourlyRate表 - 它存储员工当前的小时费率。历史汇率也存储在这里。
- RateID(int,PK)
- EffectiveDate(int,PK)
- Rate(double)
这是从TimeSheet到EmployeeHourlyRate的一对多关系。为了找到员工的工资率,我将选择最大的有效日数小于timeSheet的EntryDate。
为了方便事情,我做了一个名为TimeSheet的部分类,并向该类添加了一个名为Rate的新属性。我想做的是从填充我的TimeSheets集合的同一个查询中填充自己。我只知道没有简单干净的方式来处理这个问题。
例如,我可以这样做:
var list = from ts in Context.TimeSheets
....
选择新的TimeSheet(){
TimeSheetID = ts.TimeSheetID,
EntryDate = ts.EntryDate,
Hours = ts.Hours,
EmployeeID = ts.EmployeeID,
Rate = SomeRate //实际代码已省略
};
理论上应该有效,但由于某种原因,EF在运行时抱怨我重新使用实体生成的类(不知道为什么 - 如果我创建自己的自定义类,它可以正常工作)。然而,即使它有效,我仍然需要维护一个字段列表,并继续从我的EF映射到一个单一的类 - 即当/如果我添加新的字段到TimeSheet表时,维护成为一个问题。所以我必须重新输入所有信息也是愚蠢的。
所以我的问题是,人们通常如何处理这种情况?有没有办法在数据模型中做一些能够有效地了解我的连接规则的事情(关于根据我的EntryDate选择正确的生效日期)并处理这个问题?
我想看到你的完整的LINQ查询(包括SomeRate代码),以确切地看到你正在尝试实现什么,但也许这样可能会起作用:
警告:Air code。
public partial class TimeSheet
{
public double Rate
{
get //在这里计算你的比率...例如
{
if((this.Employee == null)||(this.Employee.EmployeeHourlyRates.Count == 0))
//抛出一个异常
EmployeeHourlyRate maxRate;
foreach(EmployeeHourlyRate rate in this.Employee.EmployeeHourlyRates)
{
if((rate.EffectiveDate< = this.EntryDate)
&&((maxRate == null)||(maxRate.EffectiveDate< rate.EffectiveDate)))
{
maxRate = rate;
}
}
if(maxRate == null)
//抛出异常
else
return maxRate.Rate;
}
}
}
编辑:添加渴望的例子加载以避免数据库往返。
var list = from Context in Context.TimeSheets.Include(Employee.EmployeeHourlyRate)
其中blah blah
选择ts;
How should I handle a custom property in a situation where I use partial classes with the EF-generated classes?
Here's the setup:
TimeSheet Table - this stores an employee's hours
- TimeSheetID (auto, int, PK)
- EntryDate (DateTime)
- Hours (int)
- EmployeeID (int)
EmployeeHourlyRate table - this stores an employee's current hourly rate. Historical rates are stored here as well.
- RateID (int, PK)
- EffectiveDate (int, PK)
- Rate (double)
This is a one to many relationship from TimeSheet to EmployeeHourlyRate. In order to find an Employee's rate, I would select the max effectiveDate less than the timeSheet's EntryDate.
In order to facilitate things, I've made a partial class called TimeSheet and added a new property called "Rate" to that class. What I would like to do is populate that myself from the same query that populates my collection of TimeSheets. I just know of no easy and clean way to handle this.
For example, I could do it this way:
var list = from ts in Context.TimeSheets
....
select new TimeSheet() {
TimeSheetID = ts.TimeSheetID,
EntryDate = ts.EntryDate,
Hours = ts.Hours,
EmployeeID = ts.EmployeeID,
Rate = SomeRate //real code has been omitted
};
This in theory should work, but for some reason the EF complains at run-time that I'm re-using an entity generated class (no idea why -- it works fine if I create my own custom class). However, even if it did work, I've still got to maintain a list of fields and keep on mapping from my EF to a single class -- i.e, maintenance becomes a problem when/if I add new fields to the TimeSheet table. It is also silly to have to re-type all that info.
So my question is, how do people generally handle this scenario? Is there a way to do something in the datamodel that would be able to effectively know my join rule (about selecting the correct effective date based on my EntryDate) and handle this?
I would like to see your full LINQ query (including the 'SomeRate' code) to see exactly what you are trying to achieve, but maybe something like this could work:
WARNING: Air code.
public partial class TimeSheet
{
public double Rate
{
get //Calculate your rate here... e.g.
{
if ((this.Employee == null) || (this.Employee.EmployeeHourlyRates.Count == 0))
//throw an exception
EmployeeHourlyRate maxRate;
foreach (EmployeeHourlyRate rate in this.Employee.EmployeeHourlyRates)
{
if ((rate.EffectiveDate <= this.EntryDate)
&& ((maxRate == null) || (maxRate.EffectiveDate < rate.EffectiveDate)))
{
maxRate = rate;
}
}
if (maxRate == null)
//throw exception
else
return maxRate.Rate;
}
}
}
EDIT: Adding example of eager loading to avoid database round trips.
var list = from ts in Context.TimeSheets.Include("Employee.EmployeeHourlyRate")
where blah blah
select ts;
这篇关于在实体框架中使用部分类与自定义属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!