Пользовательская реализация DomainService с использованием Linq to SQL - PullRequest
7 голосов
/ 01 сентября 2011

Может ли кто-нибудь указать мне пример или кратко описать, как можно было бы создать пользовательскую реализацию службы WCF RIA Services DomainService, используя Linq to SQL в качестве уровня доступа к данным, но без использование файла .dbml (это связано с тем, что модель Linq to SQL генерируется с помощью специального инструмента, сильно режется и имеет довольно большую базу данных с таблицами более 50) и без мастера VS2010 для создание службы домена (мастер зависит от наличия файла .dbml)

Вот очень простая оболочка того, что я до сих пор пробовал:

[EnableClientAccess()]
public class SubscriptionService : DomainService
{
    [Query(IsDefault = true)]
    public IQueryable<Subscription> GetSubscriptionList()
    {
        SubscriptionDataContext dc = new SubscriptionDataContext();
        var subs = dc.Subscription.Where(x => x.Status == STATUS.Active)
            .Select(x => 
            new Subscription
            {
                ID = x.ID,
                Name = x.Name
            }).ToList();

        return subs.AsQueryable();
    }

    public void InsertSubscription(Subscription sub)
    {
        if (!sub.ID.IsEmpty())
        {
            SubscriptionDataContext dc = new SubscriptionDataContext();
            Subscription tmpSub = dc.GetByID<Subscription>(sub.ID);
            if (tmpSub != null)
            {
                tmpSub.Name = sub.Name;
                dc.Save(tmpSub);
            }
            else
            {
                tmpSub = new Subscription();
                tmpSub.Name = sub.Name;
                dc.Save(tmpSub);
            }
        }
    }

    public void UpdateSubscription(Subscription sub)
    {
        if (!sub.ID.IsEmpty())
        {
            SubscriptionDataContext dc = new SubscriptionDataContext();
            Subscription tmpSub = dc.GetByID<Subscription>(sub.ID);
            if (tmpSub != null)
            {
                tmpSub.Name = sub.Name;
                dc.Save(tmpSub);
            }
        }
    }

    public void DeleteSubscription(Subscription sub)
    {
        if (!sub.ID.IsEmpty())
        {
            SubscriptionDataContext dc = new SubscriptionDataContext();
            Subscription tmpSub = dc.GetByID<Subscription>(sub.ID);
            if (tmpSub != null)
            {
                dc.Delete(tmpSub);
            }
        }
    }
}

Кажется, это работает до сих пор. Кто-нибудь видит какие-либо проблемы с этим подходом, который я мог бы пропустить? Я не хочу идти слишком далеко по неправильному пути с этим, если кто-то уже пробовал этот путь и обнаружил некоторые серьезные проблемы с ним.

Спасибо за всеобщее мнение.

1 Ответ

2 голосов
/ 14 октября 2011

Нет ничего плохого в том, чтобы сделать это таким образом.

Я сделал в основном то же самое.

вам нужно будет создать свойство, которое возвращает IQueryable для каждого запроса, ивы автоматически получите материал пропуска / получения / где в RIA Services.

[EnableClientAccess()]
public class SubscriptionService : DomainService
{
    [Query(IsDefault = true)]
    public IQueryable<Subscription> GetSubscriptionList()
    {
        using(var dc = new SubscriptionDataContext())
             return from x in dc.Subscription
                    where x.Status == STATUS.Active
                    select new Subscription { ID = x.ID, Name = x.Name };
        // make sure you don't call .ToList().AsQueryable() 
        // as you will basically load everything into memory, 
        // which you don't want to do if the client is going to be using 
        // any of the skip/take/where features of RIA Services.  
        // If you don't want to allow this, 
        // simply return an IEnumerable<Subscription>
    }
 }

Я предполагаю, что Subscription - это DTO, а не класс L2S, потому что вы создаете его явно.Просто убедитесь, что ваши DTO имеют правильные атрибуты.т.е.

public class Subscription
{
    [Key]
    // you must have a key attribute on one or more properties...
    public int ID { get; set; }
}

Если у вас есть дочерние элементы в вашем DTO, используйте атрибуты Include и Association:

public class User
{
    [Key]
    public int Id { get; set; }

    [Include]
    [Association("User_Subscriptions", "Id","UserId")]
    // 'Id' is this classes's Id property, and 'UserId' is on Subscription
    // 'User_Subscriptions' must be unique within your domain service,
    // or you will get some odd errors when the client tries to deserialize
    // the object graph.
    public IEnumerable<Subscription> Subscriptions { get; set; }
}

Также как примечание, вам не нужнополный объект для вашего метода удаления, что-то вроде этого будет работать и не позволит клиенту сериализовать весь объект и отправить его обратно, когда вам это не нужно.

public void DeleteSubscription(int id)
{
    using(var dc = new SubscriptionDataContext())
    {
        var sub = dc.GetById<Subscription>(id);
        if( sub != null ) dc.Delete(sub);
    }
}
...