EF 5 Model First Partial Class Custom Constructor如何?

时间:2013-01-23 16:53:51

标签: entity-framework constructor partial-classes ef-model-first

EF已经为我生成了一些部分类,每个都有一个构造函数,但它表示不要触摸它们(例如下面的代码),现在如果我创建自己的辅助部分类并且我想拥有一个自动设置一些的构造函数我怎么这样做,因为它会发生冲突?

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Breakdown.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Call
    {
        public Call()
        {
            this.Logs = new HashSet<Log>();
        }

        ...
    }
}

5 个答案:

答案 0 :(得分:20)

部分方法可以帮助你,在T4模板中定义一个无体的局部方法并在构造函数中调用它。

public <#=code.Escape(entity)#>()
{
    ...
    OnInit();
}

partial void OnInit();

然后在你的局部类中定义局部方法,并在构造函数中放置你想要做的事情。如果您不想做任何事情,那么您不需要定义部分方法。

partial class Entity()
{
    partial void OnInit()
    {
        //constructor stuff
        ...
    }
}

http://msdn.microsoft.com/en-us/library/vstudio/6b0scde8.aspx

答案 1 :(得分:1)

这是不可能的。

部分类本质上是同一类的一部分。

没有方法可以定义两次或覆盖(同样的规则也适用于构造函数)

但您可以使用下面提到的解决方法:

//From file SomeClass.cs - generated by the tool
public partial class SomeClass
 {
    // ...
 }


// From file SomeClass.cs - created by me
public partial class SomeClass
  {
    // My new constructor - construct from SomeOtherType
    // Call the default ctor so important initialization can be done
    public SomeClass(SomeOtherType value) : this()
      {

       }
  } 

了解更多信息,请查看Partial Classes, Default Constructors

我希望这会对你有所帮助。

答案 2 :(得分:1)

我最近想做同样的事情,最后修改了T4模板,这样我就可以手动实现自己的无参数构造函数了。要完成此任务,您可以从生成的类中删除构造函数,并将集合等的实例化移动到构造函数之外,以便:

public Call()
{
  this.Logs = new HashSet<Log>();
}

成为这个:

private ICollection<Log> logs = new HashSet<Log>();
public virtual ICollection<Log> Logs 
{ 
  get { return this.logs; } 
  set { this.logs = value; } 

}

我认为缺点是生成的类不像“干净”。也就是说,您不能只为复杂/导航类型提供自动实现的属性。

在你的model.tt文件中,你可以通过删除下面的代码,注释掉它或者只是在条件中加入一个false来阻止构造函数的生成,这样就永远不会执行:

if (propertiesWithDefaultValues.Any() || complexProperties.Any())
{
#>
  public <#=code.Escape(complex)#>()
  {
<#
    foreach (var edmProperty in propertiesWithDefaultValues)
    {
#>
      this.<#=code.Escape(edmProperty)#> =
         <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
    }

    foreach (var complexProperty in complexProperties)
    {
#>
      this.<#=code.Escape(complexProperty)#> = new
        <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
    }
#>
  }

然后在下面你需要做一些修改,为你的复杂和导航类型生成属性。添加具有对象实例化的私有var和用于访问每个私有var的属性,例如:

if (complexProperties.Any())
{
  foreach(var complexProperty in complexProperties)
  {
    //generate private var + any instantiation
    //generate property for accessing var
  }
}

根据模型的复杂程度,您可能需要修改其他区域。希望这能让你开始。

答案 3 :(得分:0)

  1. 添加基类:

     public class CallBase
     {
            protected CallBase()
            {
                Initialize();
            }
    
            protected abstract void Initialize();
     }
    
  2. 在另一个文件中添加部分类实现

     public partial class Call: CallBase
     {
        protected override void Initialize();
        {
       ...
         }
     }
    
  3. 缺点是初始化方法将在所有收集生物之前调用。

答案 4 :(得分:0)

如果我很好理解这个问题,那么在创建一个新实体时就需要这个构造函数,这个实体以前是不存在的。

我的情况是将默认值设置为所有日期时间,即将它们初始化为“开始时间”:1900-01-01。

在这种情况下,我使用实体工厂

public static T GetNewEntity<T> () {
    T e;
    try {
        e = Activator.CreateInstance<T>();
    } catch {
        e = default(T);
    }
    SetDefaults(e);

    return e;
}

每次我需要新的实体时,我都会使用

Entity e = GetNewEntity<Entity>();

使用SetDefaults:

public static void SetDefaults (object o) {
    Type T = o.GetType();
    foreach ( MemberInfo m in T.GetProperties() ) {
        PropertyInfo P = T.GetProperty(m.Name);
        switch ( Type.GetTypeCode(P.PropertyType) ) {
            case TypeCode.String :
                if ( P.GetValue(o, null) == null ) 
                    P.SetValue(o, String.Empty, null); 
                break;
            case TypeCode.DateTime :
                if ( (DateTime)P.GetValue(o, null) == DateTime.MinValue )
                    P.SetValue(o, EntityTools.dtDef, null); 
                break;
        }
    }
}

完整代码为here

考虑实体类型等可能是重写的......