使用Entity Framework Code First方法的类中的业务逻辑方法

9

我想知道在使用Entity Framework Code First方法时,是否可以在模型类上添加特定于域的方法。

例如,下面是一个虚拟方法:

public class Student
{
    public Student()
    { 

    }

    public int StudentID { get; set; }
    public string StudentName { get; set; }

    // Dummy method
    public string StudentNamePlusALetter(string letter)
    {
        return (this.StudentName + letter)
    }
}

如果不可能的话,我应该在哪里添加它们?
提前感谢你。

1
是的,你可以做到这一点。Code-first 只是类。 - xspydr
你可以这样做,但我担心关注点分离。此外,您将无法在上下文中的任何查询中使用该属性,因为SQL中不存在该操作。 - Maess
你有什么其他的技巧建议吗? - user3139803
1
您可以通过提供模型类(它们只是直接映射到存储在数据库中的实体(行)的容器)和操作模型类的模型“服务”来分离关注点,扩展上游调用者期望它们提供的功能。在上面的示例中,您可能会有一个StudentNameFormatter类,它公开了一个StudentNamePlusALetter()方法(向其中传递一个Student和一个string)。 - 48klocs
我应该扩展模型类还是创建一个新的类? - user3139803
4个回答

5
我往往通过使用两个“局部”类来实现此目的。一个用于直接映射数据库属性,另一个用于额外的内容。
在名为 Employee.cs 的文件中。
public partial class Employee
{
    public Employee()
    {

    }

    public System.Guid EmployeeUUID { get; set; }

    public string SSN { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public System.DateTime ? CreateDate { get; set; }
    public System.DateTime HireDate { get; set; }

}

然后在一个名为EmployeeExtended.cs的文件中。
public partial class Employee
{
    public string EmployeeFullName
    {
        get
        {
            return string.Format("{0}, {1} ('{2}')", this.LastName, this.FirstName, this.SSN);
        }
    }


}

请注意,上面的代码中有一个只读属性(“EmployeeFullName”),它与EF兼容并且不需要任何更改即可正常工作。

我还可以这样做:

public partial class Employee
{
    public string EmployeeFullName
    {
        get
        {
            return string.Format("{0}, {1} ('{2}')", this.LastName, this.FirstName, this.SSN);
        }
    }

    public string SomeNonTrackedDatabaseProperty { get; set; }

}

但是我需要在“SomeNonTrackedDatabaseProperty”的映射中添加“.Ignore”,因为它不是数据库中的列。

 public class EmployeeMap : EntityTypeConfiguration<Employee>
    {
        public EmployeeMap()
        {
            // Primary Key
            this.HasKey(t => t.EmployeeUUID);


            this.Property(t => t.SSN)
                .IsRequired()
                .HasMaxLength(11);

            this.Property(t => t.LastName)
                .IsRequired()
                .HasMaxLength(64);

            this.Property(t => t.FirstName)
                .IsRequired()
                .HasMaxLength(64);

            // Table & Column Mappings
            this.ToTable("Employee");
            this.Property(t => t.EmployeeUUID).HasColumnName("EmployeeUUID");

            this.Property(t => t.SSN).HasColumnName("SSN");
            this.Property(t => t.LastName).HasColumnName("LastName");
            this.Property(t => t.FirstName).HasColumnName("FirstName");
            this.Property(t => t.CreateDate).HasColumnName("CreateDate");
            this.Property(t => t.HireDate).HasColumnName("HireDate");



            this.Ignore(t => t.SomeNonTrackedDatabaseProperty);


        }
    }
}

2
如果您想要最小化配置代码,您还可以在EmployeeExtended.cs中的属性上使用[NotMapped]属性进行修饰。 - txavier
如果你想要最小化配置代码,或者不想将POCO和ORM映射的关注点分开,哈哈!这就是为什么他们给你提供选项......有些人喜欢一种方法胜过另一种。我是一个“关注点分离”的人!感谢你提供的替代方法评论。 - granadaCoder

4
当然可以,需要注意的是StudentNamePlusALetter()的值不会被存储在数据库中(因为只有属性才被序列化)。

这对于原问题中的Method()是正确的,但如果您添加了一个具有“setter”的额外属性,则需要更多内容。请参见下面的示例。 - granadaCoder

2
扩展方法在这里也不是一个坏主意。

1

使用扩展方法的完美示例,具有保持事物分离和良好结构的优势。

namespace Core.Helpers;

public static partial class Extentions
{
    public static string StudentNamePlusALetter(this Student student, string letter)
    {
        return (this.StudentName + letter); 
    }
}

你可以按照以下方式使用它:

var namePlusLetter = student.StudentNamePlusALetter("A");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接