将实体框架链接到新的Sql数据类型

时间:2015-01-01 07:11:31

标签: c# sql-server entity-framework

我正在使用ASP.NET MVC5和MS SQL 2008以及EntityFramework 6,在我的应用程序中,我有一个类体验,允许客户添加他们的经历从期间到期间的详细信息:

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,例如2009年1月,2010年10月,等等 ToDate格式将是MMM yyyy或Present,并且应大于或等于FromDate值,例如:

  1. From = 2010年1月,To = Oct 2014 ==> 接受
  2. From = 2010年1月,To = Present ==>的接受
  3. From = Oct 2014,To = Jul 2014 ==> 拒绝 To Date的值应大于From日期
  4. 我上课时间如下

    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将句点链接到sql中的数据类型句点?
    3. 任何想法都将受到赞赏

1 个答案:

答案 0 :(得分: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; }
}

更改您的句号类中的以下内容,它将是[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- enable-migration 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

希望这会对你有所帮助