Usuário com melhor resposta
WCF Data Service and Linq To SQL (Associations)

Pergunta
-
Olá,
Estou usando no meu projeto o WCF Data Service com Linq To SQL. Nele tenho duas tabelas GruposDeUsuario e Usuarios, quando eu insiro um usuário e defino o grupo (foreing key), no SaveChanges() aparece uma exceção: "An error occurred while processing this request".
Eu setei o grupo pela associação do usuário que existe no Linq To "GrupoDeUsuarios". Eu tentei definir somente o GrupoID que fica na tabela Usuarios e funcionou, mas tem algum jeito de setar por essa associação, pois antes de começar usar o WCF este jeito funcionava, e grande parte do meu projeto está assim. Com essa associação eu mostrava o nome do grupo de usuário, ou alguma outra informação sem precisar fazer um select.
Obrigado
Respostas
-
Boas Thiago,
Veja se este artigo pode te ajudar em algo: http://www.israelaece.com/post/Usando-LINQ-To-SQL-com-WCF.aspx
http://www.israelaece.com- Marcado como Resposta Thiago.Policarpo terça-feira, 3 de agosto de 2010 12:18
-
Boas Thiago,
Veja se este artigo pode te ajudar em algo: http://www.israelaece.com/post/Usando-LINQ-To-SQL-com-WCF.aspx
http://www.israelaece.comOlá, então estava com duvida onde usar o DataLoadOptions, mas pesquisando na net descobri que é no momento que faz o select para pegar os registros. Obrigado...
- Marcado como Resposta Thiago.Policarpo terça-feira, 3 de agosto de 2010 12:18
Todas as Respostas
-
Boas Thiago,
Veja se este artigo pode te ajudar em algo: http://www.israelaece.com/post/Usando-LINQ-To-SQL-com-WCF.aspx
http://www.israelaece.com- Marcado como Resposta Thiago.Policarpo terça-feira, 3 de agosto de 2010 12:18
-
Israel Aece,
Eu tentei fazer de acordo com o link, só que não consegui. Acho que não entendi muito bem. Eu fiz uma nova classe "public partial class Users", e coloquei o "public UserGroups[] RecuperarUserGroups()" (essa classe coloquei no projeto do WCF) e coloquei no DataClasses.designer.cs coloquei o IsReference=true:
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Users")]
Só que o serviço não roda. Aparece esse erro.
[global::System.Runtime.Serialization.DataContractAttribute(IsReference=true )]
public partial class Users : INotifyPropertyChanging, INotifyPropertyChanged
{
The IsReference setting for type 'WcfServiceFuturePMS.Users' is 'True', but the same setting for its parent class 'WcfServiceFuturePMS.BusinessEntityBase' is 'False'. Derived types must have the same value for IsReference as the base type. Change the setting on type 'WcfServiceFuturePMS.Users' to 'False', or on type 'WcfServiceFuturePMS.BusinessEntityBase' to 'True', or do not set IsReference explicitly.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Runtime.Serialization.InvalidDataContractException: The IsReference setting for type 'WcfServiceFuturePMS.Users' is 'True', but the same setting for its parent class 'WcfServiceFuturePMS.BusinessEntityBase' is 'False'. Derived types must have the same value for IsReference as the base type. Change the setting on type 'WcfServiceFuturePMS.Users' to 'False', or on type 'WcfServiceFuturePMS.BusinessEntityBase' to 'True', or do not set IsReference explicitly.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidDataContractException: The IsReference setting for type 'WcfServiceFuturePMS.Users' is 'True', but the same setting for its parent class 'WcfServiceFuturePMS.BusinessEntityBase' is 'False'. Derived types must have the same value for IsReference as the base type. Change the setting on type 'WcfServiceFuturePMS.Users' to 'False', or on type 'WcfServiceFuturePMS.BusinessEntityBase' to 'True', or do not set IsReference explicitly.]
System.Runtime.Serialization.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) +736692
System.Runtime.Serialization.ClassDataContractCriticalHelper.EnsureIsReferenceImported(Type type) +1816435
System.Runtime.Serialization.ClassDataContractCriticalHelper.ImportDataMembers() +46
System.Runtime.Serialization.ClassDataContractCriticalHelper..ctor(Type type) +268
System.Runtime.Serialization.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) +407
System.Runtime.Serialization.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) +86
System.Runtime.Serialization.XsdDataContractExporter.GetSchemaTypeName(Type type) +80
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.ValidateDataContractType(Type type) +27
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreatePartInfo(MessagePartDescription part, OperationFormatStyle style, DataContractSerializerOperationBehavior serializerFactory) +25
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute, MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory) +299
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter..ctor(OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory) +435
System.ServiceModel.Description.DataContractSerializerOperationBehavior.GetFormatter(OperationDescription operation, Boolean& formatRequest, Boolean& formatReply, Boolean isProxy) +220
System.ServiceModel.Description.DataContractSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch) +58
System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) +256
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +3793
System.ServiceModel.ServiceHostBase.InitializeRuntime() +60
System.ServiceModel.ServiceHostBase.OnBeginOpen() +27
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +50
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +318
System.ServiceModel.Channels.CommunicationObject.Open() +36
System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +184
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +615
[ServiceActivationException: The service '/ServiceFuturePMS.svc' cannot be activated due to an exception during compilation. The exception message is: The IsReference setting for type 'WcfServiceFuturePMS.Users' is 'True', but the same setting for its parent class 'WcfServiceFuturePMS.BusinessEntityBase' is 'False'. Derived types must have the same value for IsReference as the base type. Change the setting on type 'WcfServiceFuturePMS.Users' to 'False', or on type 'WcfServiceFuturePMS.BusinessEntityBase' to 'True', or do not set IsReference explicitly..]
System.Runtime.AsyncResult.End(IAsyncResult result) +679246
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +190
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, String routeServiceVirtualPath, Boolean flowContext, Boolean ensureWFService) +234
System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +355
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +148
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
-
Tenho também um outro jeito que estava fazendo e estava gravando os dados, porém ele duplicava o UserGroups na hora de salvar, tato para inserir quanto para alterar.
Bem o Linq To Sql setei a serialização como Unidiretional, na associação das duas tabelas desabilitei o filho, e usei um código para criar o DataClasses.denigner.cs customizado, pois precisei tirar algumas linhas do código para o UserGroup do User vir preenchido. São essas:
if ((this.serializing && (this._UserGroups.HasLoadedOrAssignedValue == false))) { return null; }
Fiz o WCF com as classes Service e IService, porém ele esta duplicando o código depois que salva.
IService:
[OperationContract] List<Users> GetUsers(); [OperationContract] bool SaveUsers(Users User); [OperationContract] bool DeleteUsers(Users User);
Service:
public bool SaveUsers(Users User) { bool Log = true; BaseModel.BeginTransaction(); if (User.IsNew) { BaseModel.DB.Users.InsertOnSubmit(User); } else { ObjectExtensions.CopyFrom(User, BaseModel.DB.Users.Single(e => e.ID == User.ID)); } try { try { BaseModel.DB.SubmitChanges(ConflictMode.ContinueOnConflict); try { BaseModel.Commit(); } catch (Exception ex) { BaseModel.RollBack(); Log = false; } } catch (ChangeConflictException) { foreach (ObjectChangeConflict temp in BaseModel.DB.ChangeConflicts) { temp.Resolve(RefreshMode.KeepCurrentValues); } Log = false; } } catch (Exception erro) { Log = false; } return Log; }
No serviçe eu retorno a bool para saber se gravou ou não. O BaseModel é uma classe para instanciar o DataClassesDataContext uma só vez. E o ObjectExtensions.CopyFrom é uma classe que peguei na net para fazer o papel do Attach.
ObjectExtensions :
public static class ObjectExtensions { public static void CopyFrom(this object origem, object destino) { // Verifica se os objetos sÆo do mesmo tipo if (origem.GetType() != destino.GetType()) throw new InvalidCastException(); // Carrega a lista de propriedades do objeto PropertyInfo[] propiedades = origem.GetType().GetProperties(); foreach (var propriedade in propiedades) { // Verifica se a propriedade ‚ publica e se possui permissÆo de escrita if (propriedade.CanWrite && propriedade.PropertyType.IsPublic && propriedade.PropertyType.IsSerializable) { // Copia o valor do objeto de origem para o objeto de destino var valor = propriedade.GetValue(origem, null); propriedade.SetValue(destino, valor, null); } } } }
Então não consegui descobrir o porque ele está duplicando.
Obrigado
-
Boas Thiago,
Eu sugeri o post, porque o LINQ To SQL traz por padrão, a navegação bidirecional. Se você tem uma relação entre Usuários e Grupos, então o problema que estava ocorrendo, deve ser devido a isso. O que eu sugiro no post é definir a propriedade IsReference do DataContract na classe pai.
http://www.israelaece.com- Sugerido como Resposta AndreAlvesLimaModerator quarta-feira, 7 de julho de 2010 23:27
-
Olá Israel,
Este erro que estava dando eu descobri o que era. Só não consegui entender onde eu uso o "public Categoria[] RecuperarCategorias()".
No meu caso eu criei o RecuperarGrupo, e coloquei na classe "public partial class Users", que seria uma classe de extenção da tabela Users.Ou eu uso este método no client memso?
Obrigado
-
-
Thiago,
Novidades quanto a essa sua dúvida?
André Alves de Lima
Visite o meu site: http://andrealveslima.spaces.live.com
Me siga no Twitter: @andrealveslima -
Boas Thiago,
Veja se este artigo pode te ajudar em algo: http://www.israelaece.com/post/Usando-LINQ-To-SQL-com-WCF.aspx
http://www.israelaece.comOlá, então estava com duvida onde usar o DataLoadOptions, mas pesquisando na net descobri que é no momento que faz o select para pegar os registros. Obrigado...
- Marcado como Resposta Thiago.Policarpo terça-feira, 3 de agosto de 2010 12:18