Linq сопоставление с несколькими таблицами - PullRequest
0 голосов
/ 19 августа 2009

Я пробираюсь через книгу Apress "Pro ASP.NET MVC Framework" (http://www.apress.com/book/view/9781430210078), и в примере автор создает ссылку на таблицу БД (а также на поддельный репозиторий), используя linq, как это: -

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.");
        }
    }

вывести в таблицу БД "Продукты" с указанным именем столбца, и все работает хорошо. Я использую эту технику в реальном приложении, так как она хорошо обрабатывает уровень доступа к БД, но мне нужно иметь возможность доступа к нескольким таблицам из моего объекта. Как я могу это сделать - мне нужно разделить мой объект на иерархию, которая отражает его таблицы, или я могу получить доступ к более чем одной таблице из основного объекта, с другими дополнительными объектами, которые имеют свои собственные таблицы? Если да, то как мне создать ссылки ORM между объектами и таблицами?

Приветствия

MH

1 Ответ

2 голосов
/ 19 августа 2009

Просто добавьте связанные таблицы в свой интерфейс репозитория, как вы это сделали для Product, а затем создайте конкретные реализации в своем классе репозитория, как и для Product.

Я использовал один и тот же шаблон в моем приложении, у меня есть два репозитория, каждый из которых обрабатывает 5-10 таблиц. Есть две разные группы таблиц, которые связаны между собой, следовательно, два хранилища.

Я бы изменил конструктор SQLRepository таким образом:

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

Вы можете легко расширить его, например, например ::1008*

    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; }
    }

EDIT - Ответ на комментарий

Вот пример того, как доставить подчиненные объекты (связанные таблицы) с помощью этого метода:

[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; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...