【问题标题】:linking entityframework to a new Sql DataType将实体框架链接到新的 Sql DataType
【发布时间】:2015-01-05 04:35:20
【问题描述】:

我正在使用 ASP.NET MVC5 和 MS SQL 2008 以及 EntityFramework 6,在我的应用程序中,我有一个类 Experiences,它允许客户从一个时期到另一个时期添加他们的体验细节:

public class Experience
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Company { get; set; }
    public string FromDate { get; set; }
    public string ToDate { get; set; }
    public string Description { get; set; }
}

FromDate 格式将为 MMM yyyy,例如 Jan 2009、Oct 2010 等 ToDate 格式将为 MMM yyyy 或 Present,并且应大于或等于 FromDate 值,例如:

  1. 从 = 2010 年 1 月,到 = 2014 年 10 月 ==> 接受
  2. 从 = 2010 年 1 月,到 = 现在 ==> 接受
  3. 从 = 2014 年 10 月,到 = 2014 年 7 月 ==> 拒绝 到日期的值应该大于开始日期

我的课程周期如下

public class Period: IComparable
{
    public Period()
    {
         this.Month="Present";
    }

    public Period(string Month,int Year)
    {
        this.Month=Month;
        this.Year=Year;
    }

    public int CompareTo(object obj)
    {
        if(obj==null)
            return 1;
        Period period = obj as Period;
        if (period != null) 
        {
            if(this.Month=="Present" && period.Month=="Present")
                return 0;
            else if(period.Month=="Present")
                return -1;
            else if(this.Month=="Present")
                return 1;
            else
            {
                DateTime date;
                DateTime periodDate;
                if(!DateTime.TryParse(string.Format("01 {0} {1}",Month,Year),out date))
                    throw new ArgumentException("Instance is not a valid Period!");             
                if(!DateTime.TryParse(string.Format("01 {0} {1}",period.Month,period.Year),out periodDate))
                    throw new ArgumentException("Object is not a valid Period!");
                return date.Date.CompareTo(periodDate.Date);
            }
        }
           else 
              throw new ArgumentException("Object is not a Period");
    }

    public override int GetHashCode()
    {
        if(this==null)
            return 0;
        else
        {
            DateTime date;
            if(!DateTime.TryParse(string.Format("01 {0} {1}",Month,Year),out date))
                throw new ArgumentException("Instance is not a valid Period!");         
            return date.GetHashCode();
        }
    }

    public override bool Equals(object obj)
    {
        return this.CompareTo(obj)==0;
    }

    public static bool operator==(Period left, Period right)
    {
        return left.Equals(right);
    }

    public static bool operator!=(Period left, Period right)
    {
        return !(left==right);
    }

    public static bool operator<(Period left, Period right)
    {
        return left.CompareTo(right)<0;
    }

    public static bool operator>(Period left, Period right)
    {
        return left.CompareTo(right)>0;
    }

    public override string ToString()
    {
        if(string.IsNullOrWhiteSpace(Month))
            return string.Empty;
        else if(Month=="Present")
            return Month;
        else 
            return string.Format("{0} {1}",Month,Year);
    }

    public string Month{get; set;}
    public int Year{get; set;}
}

示例DEMO

在 sql 中我创建了以下数据类型

create type Period from nvarchar(8) not null;

问题:

  1. 如何在 sql 中定义 Period?
  2. 如何告诉 EntityFramework 将 period 链接到 sql 中的数据类型 period?

任何想法将不胜感激

【问题讨论】:

  • 我认为 ef 中没有对此进行任何验证。您可以通过对客户端和服务器使用自定义验证来做到这一点。您还需要任何客户端验证吗?否则,您可以在服务器中添加几个代码或为其扩展新的过滤器。
  • 我认为有一种方法我可以肯定,因为 EF 是一项伟大的技术,并且确保他们没有错过这个细节,我正在等待看看是否有人可以确认这一点,否则我会感到失望跨度>
  • 尝试使用继承自ValidationAttribute的比较属性。

标签: c# sql-server entity-framework


【解决方案1】:

这里有一个解决方法

你的体验课会是这样的

public class Experience
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Company { get; set; }
    public Period FromDate { get; set; }
    public Period ToDate { get; set; }
    public string Description { get; set; }
}

在您的 period 类中更改以下内容,这将是 [ComplexType]

// change the folllowing
[NotMapped]
public string Month{get; set;}
[NotMapped]
public int Year{get; set;}

// add this property to use it for EntityFramework mapping
public string Date
{
    get
    {
        return ToString();
    }
    set
    {
        if (!string.IsNullOrEmpty(Date))
            {
                if (Date == "Present")
                    Month = "Present";
                else
                {
                    var split = Date.Split(' ');
                    Month = split[0];
                    Year = Convert.ToInt32(split[1]);
                }
            }
        }
    }

在您的映射中,您执行以下操作

 modelBuilder.Entity<Experience>()
                .Property(t => t.FromDate.Date)
                .IsRequired()
                .HasMaxLength(8);

 modelBuilder.Entity<Experience>()
            .Property(t => t.ToDate.Date)
            .IsRequired()
            .HasMaxLength(8);

要让实体框架将字段设为 Period 数据类型,您可以这样做 1-启用迁移 2- add-migration first // 这将创建一个具有数据库和表结构的文件 dbmigration 3- 在函数 Up 最后你使用 Sql(@""); 编写以下内容,这里我会为你放置 sql 语句

create function CheckPeriod(@period nvarchar(8)) -- this function will make sure that Period is valid
returns bit
as
begin
    declare @month nvarchar(3)
    if ( @period is null )
        return 0
    if( @period = 'Present')
        return 1;
    set @month=substring(@period,0,3)
    if(@month in ('Jan','Feb','Mar','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'))
        return 1;
    return isdate(@period);
end

create function CheckValidity(@right as nvarchar(8),@left as nvarchar(8)) -- this function will compare FromDate to ToDate and return valid if ToDate>FromDate
returns bit
as
begin
    if(@right='Present')
        return 0;
    if(@left='Present' and cast(@right as date)>=getdate())
        return 0;
    if(@left='Present')
        return 1;
    if(cast(@left as date)>cast(@right as date))
        return 1;
    return 0;
end

exec sp_addtype 'Period','nvarchar(8)','NOT NULL'


alter table Experiences alter column FromDate Period
alter table Experiences alter column ToDate Period

alter table Experiences
add constraint FromDateIsPeriod check ( dbo.CheckPeriod(FromDate)=1)

alter table Experiences
add constraint ToDateIsPeriod check ( dbo.CheckPeriod(ToDate)=1)

alter table Experiences
add constraint PeriodValidity check ( dbo.CheckValidity(FromDate,ToDate)=1)

如果您希望在 Down 函数中编写代码以删除函数并更改表字段以将它们返回为 nvarchar(8) 并最终删除数据类型 Period

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2017-09-14
    • 1970-01-01
    • 2021-03-28
    相关资源
    最近更新 更多