如何使用Entity Framework从DB实现自定义对象实现

时间:2012-06-26 10:51:51

标签: entity-framework

我对Entity Framework相当新,并研究将一些遗留数据访问代码转换为使用EF。我想知道EF中是否可以使用以下内容,如果是的话。 假设我有一个像这样的客户表

CustomerId | ProductId | StartDate | EndDate
--------------------------------------------
100        | 999       | 01/01/2012| null

假设我还将产品数据从其他地方(如XML文件)加载为产品对象的缓存。

public class Customer
{
    public int CustomerId {get;set;}
    public int Product {get;set}
    public DateTime StartDate {get;set;}
    public DateTime? EndDate {get;set;}    

}

public class Product
{
    public int ProductId {get;set;}
    public int Description {get;set}
}

目前在CustomerDal类中,该方法使用StoredProc来获取像这样的

客户对象
Customer GetCustomer(int customerId)
{
    // setup connection, command, parameters for SP, loop over datareader
    Customer customer = new Customer();
    customer.CustomerId = rdr.GetInt32(0);
    int productId = rdr.GetInt32(1);
    // ProductCache is a singleton object that has been initialised before
    customer.Product = ProductCache.Instance.GetProduct(productId);
    customer.StartDate = rdr.GetDateTime(2);
    customer.EndDate = rdr.IsDbNull(3) ? (DateTime?)null : rdr.GetDateTime(3);
    return customer;
}

我的问题是,当它实现Customer对象时,它可能使用EF,它不是从DB设置Product属性,而是通过另一种方法设置,在本例中是从内存缓存中设置。类似地,在保存新的Customer对象时,它只从Products属性获取ProductId并将值保存在DB中。

1 个答案:

答案 0 :(得分:0)

如果您将产品实例附加到EF上下文,那么在加载Customer时,只要与数据库关联的产品,Product属性将自动从内存中填充而无需查询数据库。客户已经附上了。

例如,从这些实体开始:

public class Customer
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public string Name { get; set; }
    public Product Product { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Description { get; set; }
}

产品将在全球范围内提供,为简单起见,我们将其设为静态类:

public static class CachedProducts
{
    public static Product[] All
    {
        get
        {
            return new Product[] { new Product { Id = 1, Description = "Foo" } };
        }
    }
}

考虑到这一点,我们只需要确保每个EF上下文都以附加到它的所有产品开头:

public class CustomerContext : DbContext
{
    public CustomerContext()
    {
        // Attach products to context
        Array.ForEach(CachedProducts.All, p => this.Products.Attach(p));
    }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Product> Products { get; set; }
}

最后,为了使样本完整且可运行,我们为数据库设定种子,请求客户并打印相关的产品说明:

public class DatabaseInitializer : CreateDatabaseIfNotExists<CustomerContext>
{
    protected override void Seed(CustomerContext context)
    {
        var p = new Product { Id = 1, Description = "Foo" };
        var c = new Customer { Id = 1, Product = p, Name = "John Doe" };

        context.Customers.Add(c);
        context.SaveChanges();
    }
}


class Program
{
    static void Main(string[] args)
    {
        Database.SetInitializer<CustomerContext>(new DatabaseInitializer());

        using (var context = new CustomerContext())
        {
            var customer = context.Customers.Single(c => c.Id == 1);

            Console.WriteLine(customer.Product.Description);
        }
    }
}

如果将分析器附加到SQL Server,您会注意到客户是从数据库加载的,但是由于它已经附加到上下文,因此不会执行任何查询来获取产品。这在加载客户时以及使用关联产品保存新客户时都有效。

免责声明:我不是EF专家,因此这种方法可能会产生一些我不能考虑的不良副作用。