2013-03-18 96 views
2

我在我的实体框架5模型中定义了一个枚举,我使用它来定义表格中某个字段的类型,例如,使用Description属性修饰EF对象模型的枚举?

public enum PrivacyLevel : byte { 
    Public = 1, 
    FriendsOnly = 2, 
    Private = 3, 
} 

我有一个表Publication具有tinyint字段PrivacyLevel,这是我在EF模型已经映射到使用上面定义的PrivacyLevel类型,使用方法描述here

但我也希望能够显示每个枚举值的字符串描述。这是我过去为枚举完成的,并且使用Description属性对它们进行了修饰,例如

public enum PrivacyLevel : byte { 
    [Description("Visible to everyone")] 
    Public = 1, 
    [Description("Only friends can view")] 
    FriendsOnly = 2, 
    [Description("Only I can view")] 
    Private = 3, 
} 

我有一些代码将枚举转换为字符串,通过检查它们是否具有Description属性,并且工作正常。但在这里,因为我必须在我的模型中定义枚举,所以底层代码是自动生成的,我没有稳定的地方来装饰它们。

解决方法的任何想法?

+0

更好地使用代码,然后:) – 2013-03-18 11:20:28

+0

@Jayantha - 是否有可能在中间切换曲目?项目中的其他一切都是DB首先。 – 2013-03-18 11:22:43

+0

啊,是的,你可以做到。 – 2013-03-18 11:23:27

回答

2

最后我想出了一个更简单的解决方案:我举st使用扩展方法来获取枚举的描述。这也使得本地化更容易,所以我可以使用资源字符串。

public static string Description(this PrivacyLevel level) { 
    switch (level) { 
    case PrivacyLevel.Public: 
     return Resources.PrivacyPublic; 
    case PrivacyLevel.FriendsOnly: 
     return Resources.PrivacyFriendsOnly; 
    case PrivacyLevel.Private: 
     return Resources.PrivacyPrivate; 
    default: 
     throw new ArgumentOutOfRangeException("level"); 
    } 
} 
14

不知道这是你以后的样子,但是从我的理解我会尽可能的清楚,因为你有一个具体的数据库第一种方法,你可以抽象你的实体模型到ViewModels使用Dto通过AutoMapper进行处理。

使用automapper配置文件,您可以快速为各种环境和情景的灵活性和适应性

所以这里的设置配置文件是这样的“枚举”,这是害我一个问题

这里是我的视图模型此枚举

首先这里是我的布局

这里是一个简单的映射帐户实体的视图模型的账户

public class AccountProfile : Profile 
{ 
    protected override void Configure() 
    { 
     // Map from Entity object to a View Model we need or use 
     // AutoMapper will automatically map any names that match it's conventions, ie properties from Entity to ViewModel have exact same name properties 

     Mapper.CreateMap<Account, AccountViewModel>() 
       .ForMember(model => model.CurrentPrivacy, opt => opt.MapFrom(account => (PrivacyLevelViewModel)account.PrivacyLevel)); 

     Mapper.CreateMap<Account, EditAccountViewModel>() 
      .ForMember(model => model.SelectedPrivacyLevel, opt => opt.MapFrom(account => (PrivacyLevelViewModel) account.PrivacyLevel)); 

     // From our View Model Changes back to our entity 

     Mapper.CreateMap<EditAccountViewModel, Account>() 
       .ForMember(entity => entity.Id, opt => opt.Ignore()) // We dont change id's 
       .ForMember(entity => entity.PrivacyLevel, opt => opt.MapFrom(viewModel => (PrivacyLevel)viewModel.NewSelectedPrivacyLevel)); 

    } 


} 

注意,这并不一定适用于MVC,这可能是用于WPF或其他与Web无关的应用程序,但由于它是一种很好的解释方式,所以我在此示例中使用了MVC。

当我第一次得到我的个人资料HTTP GET请求,我抓住从数据库 实体和地图什么是我真正需要的视图

public ActionResult Index() 
{ 
    // Retrieve account from db 
    var account = new Account() { Id = 1, Name = "Patrick", AboutMe = "I'm just another dude", ProfilePictureUrl = "", PrivacyLevel = PrivacyLevel.Private, Friends = new Collection<Account>() }; 
    // ViewModel abstracts the Entities and ensures behavour that only matters to the UI 
    var accountViewModel = Mapper.Map<AccountViewModel>(account); 

    return View(accountViewModel); // strongly typed view model 
} 

所以我的个人资料索引视图可以用我的枚举视图模型

下面是输出

现在,当我想改变我的隐私设置是什么,我可以创造一个新的EditAccountViewModel,让我在下拉

public class EditAccountViewModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string AboutMe { get; set; } 
    public int NewSelectedPrivacyLevel { get; set; } 
    public PrivacyLevelViewModel SelectedPrivacyLevel { get; set; } 

    public SelectList PrivacyLevels 
    { 
     get 
     { 
      var items = Enum.GetValues(typeof (PrivacyLevelViewModel)) 
       .Cast<PrivacyLevelViewModel>() 
       .Select(viewModel => new PrivacyLevelSelectItemViewModel() 
       { 
        Text = viewModel.DescriptionAttr(), 
        Value = (int)viewModel, 
       }); 

      //SelectPrivacyLevel was mapped by AutoMapper in the profile from 
      //original entity value to this viewmodel 
      return new SelectList(items, "Value", "Text", (int) SelectedPrivacyLevel); 
     } 
    } 
} 

提交一份新的价值现在,一旦我送我感兴趣的部分是我如何修改数据库中的“真实”实体,并更新了隐私设置

将表单提交回我的编辑操作后,我可以获得原始的真实数据库实体和然后合并陈GES如果视图模型状态有效

AutoMapper允许您配置的ViewModels如何映射到实体, 如果一些属性应,改变从整数实体字符串值视图模型, 也许你想一个枚举真的是一个字符串在“视图”,只有数据库的枚举, 与自动映射器,它允许你配置所有这些scenarious,并通过约定 你不需要配置“每一个属性”,如果你的看法模型具有相同的 属性名称/骆驼案例大写。

最后,才可以使用这些配置文件,您必须在应用程序入口点加载它们,喜欢的Global.asax或主。

AutoMapper只需要“配置”一次即可加载应用程序中定义的任何种类的配置文件。有了一些反思,你可以加载所有配置文件在汇编此代码:

public class AutoMapperConfig 
{ 
    public static void RegisterConfig() 
    { 
     Mapper.Initialize(config => GetConfiguration(Mapper.Configuration)); 
    } 

    private static void GetConfiguration(IConfiguration configuration) 
    { 
     configuration.AllowNullDestinationValues = true; 
     configuration.AllowNullCollections = true; 

     IEnumerable<Type> profiles = Assembly.GetExecutingAssembly().GetTypes().Where(type => typeof(Profile).IsAssignableFrom(type)); 

     foreach (var profile in profiles) 
     { 
      configuration.AddProfile(Activator.CreateInstance(profile) as Profile); 
     } 
    } 
} 

我叫我的Global.asax中配置:有关如何使用AutoMapper

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 

    WebApiConfig.Register(GlobalConfiguration.Configuration); 
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    AutoMapperConfig.RegisterConfig(); // AutoMapperConfig.cs 
} 

的更多信息,以及它如何有利于你可以发现 这里:

AutoMapper Github

+1

哇,现在,这就是所谓的努力成为一个答案!至少在努力之前+1,甚至在我开始工作之前! – 2013-03-18 15:29:57

+1

谢谢:) *湿巾汗* – 2013-03-18 15:36:22

+0

嗨夏尔,这是否最终成为你以后?有兴趣知道你是如何得到的,因为没有人回答你。 – 2013-04-05 02:20:16

0

一些其他的想法: 使用byte PrivacyLevelByte在EF类。对于您定义属性

PrivacyLevel PrivacyLevelEnum 
{ 
    get { return (PrivacyLevel)PrivacyLevelByte; } 
    set { PrivacyLevelByte = (byte)value;} 
} 

,并确定在你的代码PrivacyLevel枚举,而不是由EF设计特定模型创建其他partial class。 这允许你处理任何属性,但仍然给你EF模型的枚举属性。