Linq映射到多个表

时间:2009-08-19 15:02:40

标签: asp.net-mvc

我通过Apress“Pro ASP.NET MVC Framework”(http://www.apress.com/book/view/9781430210078)一书,并在一个示例中,作者使用linq创建了一个指向db表(以及虚假存储库)的链接像这样: -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq.Mapping;

namespace DomainModel.Entities
{
    [Table(Name = "Products")]
    public class Product
    {
        [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
        public int ProductID { get; set; }

        [Column] public string Name { get; set; }
        [Column] public string Description { get; set; }
        [Column] public decimal Price { get; set; }
        [Column] public string Category { get; set; }
        public string this[string propName]
        {
          get {
            if ((propName == "Name") && string.IsNullOrEmpty(Name))
                return "Please enter a product name";
            if ((propName == "Description") && string.IsNullOrEmpty(Description))
                return "Please enter a description";
            if ((propName == "Price") && (Price < 0))
                return "Price must not be negative";
            if ((propName == "Category") && string.IsNullOrEmpty(Category))
                return "Please specify a category";
            return null;
        }
    }
    public string Error { get { return null; } } // Not required    }
}

创建界面: -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DomainModel.Entities;

namespace DomainModel.Abstract
{
    public interface IProductsRepository
    {
        IQueryable Products { get; }
        void SaveProduct(Product product);
        void DeleteProduct(Product product);
    }
}

假存储库(未包含),然后是真正的数据库连接存储库: -

using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DomainModel.Abstract;
using System.Data.Linq;
using DomainModel.Entities;

namespace DomainModel.Concrete
{
    public class SqlProductsRepository : IProductsRepository
    {
        private Table productsTable;
        public SqlProductsRepository(string connectionString)
        {
            productsTable = (new DataContext(connectionString)).GetTable();
        }

        public IQueryable Products
        {
            get { return productsTable; }
        }

        public void SaveProduct(Product product)
        {
            EnsureValid(product, "Name", "Description", "Category", "Price");

            // If it's a new product, just attach it to the DataContext
            if (product.ProductID == 0)
                productsTable.InsertOnSubmit(product);
            else {
                // If we're updating an existing product, tell the DataContext
                // to be responsible for saving this instance
                productsTable.Attach(product);
                // Also tell the DataContext to detect any changes since the last save
                productsTable.Context.Refresh(RefreshMode.KeepCurrentValues, product);
            }

            productsTable.Context.SubmitChanges();
        }

        public void DeleteProduct(Product product)
        {
            productsTable.DeleteOnSubmit(product);
            productsTable.Context.SubmitChanges();
        }

        private void EnsureValid(IDataErrorInfo validatable, params string[] properties)
        {
            if (properties.Any(x => validatable[x] != null))
                throw new InvalidOperationException("The object is invalid.");
        }
    }

关闭指定列名称的DB表“Products”,它可以很好地工作。我在一个真实的应用程序中使用这种技术,因为它很好地处理数据库访问层,但我需要能够从我的对象访问几个表。我该怎么做 - 我是否需要将我的对象拆分为反映其表的层次结构,或者我可以从主对象访问多于一个表,还有其他附加对象挂起它有自己的表?如果是,那么如何在对象和表之间创建ORM链接?

干杯

MH

1 个答案:

答案 0 :(得分:2)

只需将相关表添加到存储库界面,就像使用Product一样,然后在存储库类中创建具体实现,就像对Product一样。

我在我的应用程序上使用了相同的模式,我有两个存储库,每个存储库处理5-10个表。有两组不同的表是相关的,因此有两个存储库。

我会改变SQLRepository构造函数:

    public SqlProductsRepository(string connectionString)
    {
        DataContext dc = new DataContext(connectionString);
        productsTable = dc.GetTable<Product>();
    }

然后您可以轻松扩展它,例如:

    private Table<Order> ordersTable;

    public SqlProductsRepository(string connectionString)
    {
        DataContext dc = new DataContext(connectionString);
        productsTable = dc.GetTable<Product>();
        ordersTable = dc.GetTable<Order>();
    }

    IQueryable<Order> Orders
    {
        get { return from o in ordersTable select o; }
    }

编辑 - 回答评论

以下是如何通过此方法传递下级对象(相关表)的示例:

[Table(Name="Projects")]
public class Project
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
    public Guid ID { get; set; }
    [Column]
    public String Name { get; set; }
    [Column]
    public bool Active { get; set; }

    [Association(ThisKey="ID", OtherKey = "ProjectID")]
    private EntitySet<ProjectDate> _projectDates = new EntitySet<ProjectDate>();
    public IQueryable<ProjectDate> ProjectDates
    {
        get { return _projectDates.AsQueryable(); }
    }
}

ProjectDate类的完整性

[Table(Name="ProjectDates")]
public class ProjectDate
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
    public Guid ID { get; set; }
    [Column]
    public Guid ProjectID { get; set; }
    [Column]
    public DateTime TargetDate { get; set; }
    [Column(CanBeNull = true)]
    public DateTime? ActualDate { get; set; }
    [Column(CanBeNull=true, IsDbGenerated = true)]
    public DateTime? Created { get; set; }

    private EntityRef<Project> _project;
    [Association(ThisKey = "ProjectID", Storage = "_project", OtherKey = "ID")]
    public Project Project
    {
        get { return _project.Entity; }
        set { _project.Entity = value; ProjectID = _project.Entity.ID; }
    }
}