Как сначала сделать запросы к сервису WCF с моделью / данными EF - PullRequest
0 голосов
/ 28 марта 2012

У меня есть клиентский проект и первый проект модели MVC3 EF, который предоставляет клиенту сервис WCF. Я новичок в EF, и некоторые вещи не так ясны.

Давайте предположим, что служба Northwind с сущностью Product, если я хочу сделать простой запрос, например, вернуть продукты с определенной ценой, где мне написать код для запроса?

На стороне сервера есть только EDM и сама служба, и это довольно просто, едва ли есть какой-либо код.

На клиенте у меня есть Product класс модели и NorthwindContext, а также класс ProdcutsPageViewModel (это проект MVVM)

Итак, мой вопрос: как и где я могу делать запросы к БД? сделать это со стороны клиента, прикрепив код LINQ к URI? сделать это со стороны сервера, добавив новые методы в службу? Я был бы признателен, если бы вы могли объяснить это новичку,

Спасибо!

Вот часть кода:

На сервере , класс обслуживания NorthwindODataService:

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NorthwindODataService : DataService<NorthwindEntities>
{
    private readonly IUserPrivilegesRepository userPrivilegesRepository;
    private readonly IClaimsIdentity identity;

    public NorthwindODataService()
        : this(HttpContext.Current.User.Identity as IClaimsIdentity, new InfrastructureEntities())
    {
    }

    public NorthwindODataService(IClaimsIdentity identity, IUserPrivilegesRepository userPrivilegesRepository)
    {
        this.identity = identity;
        this.userPrivilegesRepository = userPrivilegesRepository;
    }

    protected string UserId
    {
        get
        {
            var nameIdentifierClaim = this.identity.Claims.SingleOrDefault(c => c.ClaimType == ClaimTypes.NameIdentifier);
            if (nameIdentifierClaim == null)
            {
                throw new DataServiceException(401, "Unauthorized", "The request requires authentication.", "en-US", null);
            }

            return nameIdentifierClaim.Value;
        }
    }

    /// <summary>
    /// Initializes service-wide policies. This method is called only once.
    /// </summary>
    /// <param name="config"></param>
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("Products", EntitySetRights.All);
        config.SetEntitySetAccessRule("Categories", EntitySetRights.AllRead);
        config.SetEntitySetAccessRule("Suppliers", EntitySetRights.AllRead);

        config.SetEntitySetPageSize("Products", 20);
        config.SetEntitySetPageSize("Categories", 20);
        config.SetEntitySetPageSize("Suppliers", 20);

        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        config.UseVerboseErrors = true;
    }

    /// <summary>
    /// Define a query interceptor for the Products entity set.
    /// </summary>
    /// <returns></returns>
    [QueryInterceptor("Products")]
    public Expression<Func<Product, bool>> OnQueryProducts()
    {
        this.ValidateAuthorization("Products", PrivilegeConstants.SqlReadPrivilege);

        // The user has Read permission.
        return p => true;
    }

    /// <summary>
    /// Define a query interceptor for the Categories entity set.
    /// </summary>
    /// <returns></returns>
    [QueryInterceptor("Categories")]
    public Expression<Func<Category, bool>> OnQueryCategories()
    {
        this.ValidateAuthorization("Categories", PrivilegeConstants.SqlReadPrivilege);

        // The user has Read permission.
        return p => true;
    }

    /// <summary>
    /// Define a query interceptor for the Suppliers entity set.
    /// </summary>
    /// <returns></returns>
    [QueryInterceptor("Suppliers")]
    public Expression<Func<Supplier, bool>> OnQuerySuppliers()
    {
        this.ValidateAuthorization("Suppliers", PrivilegeConstants.SqlReadPrivilege);

        // The user has Read permission.
        return p => true;
    }

    /// <summary>
    /// Define a change interceptor for the Products entity set.
    /// </summary>
    /// <param name="product"></param>
    /// <param name="operations"></param>
    [ChangeInterceptor("Products")]
    public void OnChangeProducts(Product product, UpdateOperations operations)
    {
        if (operations == UpdateOperations.Change)
        {
            this.ValidateAuthorization("Products", PrivilegeConstants.SqlUpdatePrivilege);

            var entry = default(ObjectStateEntry);
            if (this.CurrentDataSource.ObjectStateManager.TryGetObjectStateEntry(product, out entry))
            {
                // Reject changes to a discontinued Product.
                // Because the update is already made to the entity by the time the 
                // change interceptor in invoked, check the original value of the Discontinued
                // property in the state entry and reject the change if 'true'.
                if ((bool)entry.OriginalValues["Discontinued"])
                {
                    throw new DataServiceException(400, "Bad Request", "A discontinued product cannot be modified.", "en-US", null);
                }
            }
            else
            {
                throw new DataServiceException(404, "Not Found", "The requested product could not be found in the data source.", "en-US", null);
            }
        }
        else if (operations == UpdateOperations.Add)
        {
            this.ValidateAuthorization("Products", PrivilegeConstants.SqlCreatePrivilege);
        }
        else if (operations == UpdateOperations.Delete)
        {
            this.ValidateAuthorization("Products", PrivilegeConstants.SqlDeletePrivilege);

            var entry = default(ObjectStateEntry);
            if (this.CurrentDataSource.ObjectStateManager.TryGetObjectStateEntry(product, out entry))
            {
                // Only a discontinued Product can be deleted.
                if (!(bool)entry.OriginalValues["Discontinued"])
                {
                    throw new DataServiceException(400, "Bad Request", "Products that are not discontinued cannot be deleted.", "en-US", null);
                }
            }
            else
            {
                throw new DataServiceException(404, "Not Found", "The requested product could not be found in the data source.", "en-US", null);
            }
        }
    }

    private static string BuildMessage(string entitySetName, string privilege)
    {
        var message = string.Empty;
        switch (privilege)
        {
            case PrivilegeConstants.SqlCreatePrivilege:
                message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to create new rows in the {0} entity set.", entitySetName);
                break;
            case PrivilegeConstants.SqlReadPrivilege:
                message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to query the {0} entity set.", entitySetName);
                break;
            case PrivilegeConstants.SqlUpdatePrivilege:
                message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to update rows in the {0} entity set.", entitySetName);
                break;
            case PrivilegeConstants.SqlDeletePrivilege:
                message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to delete rows in the {0} entity set.", entitySetName);
                break;

            default:
                message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to access the {0} entity set.", entitySetName);
                break;
        }

        return message;
    }

    private void ValidateAuthorization(string entitySetName, string privilege)
    {
        if (!this.userPrivilegesRepository.HasUserPrivilege(this.UserId, privilege))
        {
            // The user does not have Read permission.
            throw new DataServiceException(401, "Unauthorized", BuildMessage(entitySetName, privilege), "en-US", null);
        }
    }
}

}

на клиенте , Product модель класса:

[EntitySetAttribute("Products")]
[DataServiceKeyAttribute("ProductID")]
public class Product : INotifyPropertyChanged
{
    private int id;
    private string productName;
    private int? supplierID;
    private int? categoryID;
    private string quantityPerUnit;
    private decimal? unitPrice;
    private short? unitsInStock;
    private short? unitsOnOrder;
    private short? reorderLevel;
    private bool discontinued;

    public event PropertyChangedEventHandler PropertyChanged;

    public int ProductID
    {
        get
        {
            return this.id;
        }

        set
        {
            this.id = value;
            this.OnPropertyChanged("ProductID");
        }
    }

    public string ProductName
    {
        get
        {
            return this.productName;
        }

        set
        {
            this.productName = value;
            this.OnPropertyChanged("ProductName");
        }
    }

    public int? SupplierID
    {
        get
        {
            return this.supplierID;
        }

        set
        {
            this.supplierID = value;
            this.OnPropertyChanged("SupplierID");
        }
    }

    public int? CategoryID
    {
        get
        {
            return this.categoryID;
        }

        set
        {
            this.categoryID = value;
            this.OnPropertyChanged("CategoryID");
        }
    }

    public string QuantityPerUnit
    {
        get
        {
            return this.quantityPerUnit;
        }

        set
        {
            this.quantityPerUnit = value;
            this.OnPropertyChanged("QuantityPerUnit");
        }
    }

    public decimal? UnitPrice
    {
        get
        {
            return this.unitPrice;
        }

        set
        {
            this.unitPrice = value;
            this.OnPropertyChanged("UnitPrice");
        }
    }

    public short? UnitsInStock
    {
        get
        {
            return this.unitsInStock;
        }

        set
        {
            this.unitsInStock = value;
            this.OnPropertyChanged("UnitsInStock");
        }
    }

    public short? UnitsOnOrder
    {
        get
        {
            return this.unitsOnOrder;
        }

        set
        {
            this.unitsOnOrder = value;
            this.OnPropertyChanged("UnitsOnOrder");
        }
    }

    public short? ReorderLevel
    {
        get
        {
            return this.reorderLevel;
        }

        set
        {
            this.reorderLevel = value;
            this.OnPropertyChanged("ReorderLevel");
        }
    }

    public bool Discontinued
    {
        get
        {
            return this.discontinued;
        }

        set
        {
            this.discontinued = value;
            this.OnPropertyChanged("Discontinued");
        }
    }

    public static Product CreateProduct(int productID, string productName, bool discontinued)
    {
        return new Product
        {
            ProductID = productID,
            ProductName = productName,
            Discontinued = discontinued,
        };
    }

    protected virtual void OnPropertyChanged(string changedProperty)
    {
        var propertyChanged = this.PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(changedProperty));
        }
    }
}

}

И NorthwindContext класс:

public class NorthwindContext : DataServiceContext
{
    public NorthwindContext(Uri serviceRoot)
        : base(serviceRoot)
    {
        this.MergeOption = MergeOption.OverwriteChanges;
        this.SaveChangesDefaultOptions = SaveChangesOptions.ContinueOnError;
    }

    public void AddToCategories(Category category)
    {
        this.AddObject("Categories", category);
    }

    public void AddToProducts(Product product)
    {
        this.AddObject("Products", product);
    }

    public void AddToSuppliers(Supplier supplier)
    {
        this.AddObject("Suppliers", supplier);
    }

    public void AttachToCategories(Category category)
    {
        this.AttachTo("Categories", category);
    }

    public void AttachToProducts(Product product)
    {
        this.AttachTo("Products", product);
    }

    public void AttachToSuppliers(Supplier supplier)
    {
        this.AttachTo("Suppliers", supplier);
    }
}

}

а вот класс ProductsPageViewModel:

 public class ProductsPageViewModel : ListViewModel<Product>
{
    public ProductsPageViewModel()
        : this(Deployment.Current.Dispatcher, App.CloudClientFactory.ResolveNorthwindContext())
    {
    }

    public ProductsPageViewModel(Dispatcher dispatcher, NorthwindContext northwindContext)
        : base(dispatcher, northwindContext)
    {
    }

    protected override string EntitySetName
    {
        get
        {
            return "Products";
        }
    }
}

}

Ответы [ 2 ]

0 голосов
/ 05 октября 2012

paramosh,

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

0 голосов
/ 28 марта 2012

Когда вы работаете с EF, он не предполагает никаких прямых запросов к базе данных.Потратил некоторое время, читая, что такое «Дизайн, управляемый доменом».Описана стратегия Persistent Ignorance, которая означает, что при проектировании вашей системы вы вообще не должны рассматривать хранение данных.Работа только с моделью.Шаблон Data Mapper описывает место, где должны быть выполнены все вещи, связанные с базой данных. Здесь - хорошая статья, которая, я думаю, может вам помочь.
Еще один совет, не забывайте, что MVC поддерживает спокойный стиль веб-разработки.Использование этих возможностей должно быть полезным в вашем дизайне.

...