I have WCF service responsible for exposing services and connecting with local database MSSQL.
I generate client of this service in a few projects, e.g. Proj1 and Proj2. In Proj3 I have references to Proj1 and Proj2. I want to use types from database, but they are in different namespaces (Proj1.ServiceReference.TablePerson, Proj2.ServiceReference.TablePerson).
How can I resolve this problem? I suppose using sth like converted/adapter for each type (table) is not the best solution.
Have a shared dll with your classes and reference it form the server and from the client.
When you create a wcf reference, make sure that "reuse types from existing assemblies" is set. This will make generated proxies rely on the shared dll code and WILL NOT create new proxy types each time you create a web reference.
What you should do is create a separate project to create your service references in, and then have Proj1 Proj2 and Proj3 all reference that project. That way you will only have to generate one set of classes for your service reference.
Related
I want to create a class library and publish it to artifactory. However, I have organized my solution such that there is a public "Client" project, then an internal "Domain" project that contains business logic that I do not want to publish.
My issue is that apparently I have to publish the Domain project if the Client project depends on it. If I don't, then when I attempt to install the Client dependency in another project, I get an error stating that Domain cannot be found.
Is it possible to accomplish what I'm looking for, i.e., an entire assembly that is only accessible to another assembly in the same solution? The key point is that I want the classes within Domain to not be accessible to other projects. I know I could put them in the Client assembly and mark the internal, but I prefer the organization of having an entirely separate project, as well as not having to mark every single class internal.
I have this solution in VS 2017 which has multiple projects:
Example.DomainModels
Example.DataAccess
Example.Infrastructure
Example.Web
So well, my Web project references Infrastructure and the Infrastructure project references DataAccess as well as DomainModels projects. The solution is working fine.
However, if inside my Web project, if I try to access any of the entities from the DomainModels, I can easily access that without any errors, even though Web project doesn't have any reference to the DomainModels.
Can you please help me understand how this referencing of the project works? Is it because the web project has indirect reference to the DomainModels (Web -> Infrastructure -> DomainModels)?
Thanks.
Indeed , as per your comments web will have reference to all other projects
When you compile , The Infrastructure will be having references dataaccess and domain model namespaces attached to it hence you are able to access the types or namespaces present in dataaccess and domain models from web since you are refering Infrastructure from web .
Please investigate the Onion architecture: https://social.technet.microsoft.com/wiki/contents/articles/36655.onion-architecture-in-asp-net-core-mvc.aspx
The Domain Model should not reference anything. In order to achieve this; you should investigate dependancy inversion. I asked a question recently about dependancy inversion here: Execute code in a class library when you do not have a reference to that class library
If you want to divorce the domain layer from the web then you could introduce a service layer.
I have seen this question before (here for one), however the solution is to not reuse referenced assemblies.
I need to reuse included assemblies because multiple services reference the same shared Objects.
If I do not reuse the assemblies I get namespace errors because the same Object is referenced through
different namespaces. (ie. Service1.Object, Service2.Object)
In short, I need the generated Client class that extends the ClientBase for the web service but I cannot untick the reuse referenced assemblies as I need shared Objects with the same namespace. Any suggestions?
You can generate your client proxy with svcutil.exe and use the /r switch to specify assemblies that you want referenced instead of re-emitted in the auto-generated client proxy code.
ProjACommon
ProjBSvc
References ProjACommon
ProjCClient
References ProjACommon
You want a client that references ProjA types and/or code rather than them being auto-generated into a new namespace within C
After building ProjBSvc exec the following, which outputs .wsdl & .xsd
svcutil.exe ProjBSvc.dll
2nd consume the wsdl & xsd to generate a proxy/client:
svcutil.exe *.wsdl *.xsd /o:<ProjCClientPath>/Client.cs /r:ProjACommon.dll
ProjCClient references Client.cs generated from previous steps
Build and examine with the object browser and you will see the types in C referencing the types in A instead of new types with the same name in C's namespace.
You may want /tcv and /n as well as other switches to meet your needs.
Here is an article that may help. It also links to the Microsoft documentation for svcutil
Use a mapper, meaning you will have to duplicate the models(objects) and have a class the maps the objects from one namespace to the next.
I've searched for an answer on google using:
"The type 'Microsoft.SqlServer.Management.Smo.Server' is defined in an assembly that is not referenced."
Why does using Microsoft Sql Server Management Objects (SMO) in the DAL require references to SMO dlls in a referenced project?
using sql smo in referenced projects
sql smo in layered solutions
sql smo reference requirements
and probably a few others and have not found a solution or explanation to this issue.
Admittedly, I'm only a journeyman googler, so if someone wishes to power level me and point the way to an existing resource, I'll gladly go spelunking from there.
Here's my set up:
I've got a layered solution: DAL, Business Logic, Services, UI. There's a hosts project that hosts the services. I'm actually using the VS2010 extension layerguidance.codeplex.com, which is quite nice, to set up all these projects. I'm using SQL Server 2008 Express and SMO v 10. All solution projects are referenced using Project References. All projects compile to a common top level Bin folder.
Now the problem:
Among the classes in the DAL I have an SmoTasks class which handles interfacing with SMO objects and a Utilities class which abstracts from SmoTasks and provides acces to its functions without requiring any SMO objects for parameters, so that referencing projects (read: Business Logic Layer) can interface using non-SMO types. All is well in the DAL, it compiles fine, the methods pass their tests - it feels good about its place in my world. Then in the BLL I have a component which handles using the Utilities class to perform database configuration for the application which will be exposed via the services. The BLL uses a project reference to the DAL and sees the DAL classes (a la intellisense) as expected. When I compile though, I get:
The type 'Microsoft.SqlServer.Management.Smo.Server' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91'.
The code in BLL looks like this:
public bool CreateTables(string connectionString)
{
bool result = default(bool);
// Data access component declarations.
Utilities utilities = new Utilities();
// Step 1 - Calling CreateTables on Utilities.
result = utilities.CreateTables(connectionString);
return result;
}
The line the error points to is:
result = utilities.CreateTables(connectionString);
I could, obviously, add the SMO references to the BLL and then the BLL would be happy, but that violates my design goal of loosely coupled projects. If I add the SMO assemblies to the BLL, it compiles and then referencing BLL objects in the services layer doesn't cause a complaint. My question is, why? More specifically: Why does the BLL need references to SMO when the Utilities class in the DAL already abstracts away the SMO types?
What I want is everything database related to live in the DAL (duh) and only business logic in the BLL (double duh). Is there another way to achieve this using SMO that I have overlooked?
Thank you for your valuable time and answers, I humbly await your responses
Edit:
I've adjusted my solution based on suggestions by Chris, verified that I'm using project refs (I am), readded the references to SMO in the DAL using Muse.VSExtensions to add GAC reference, before I had been browsing and adding manually, then I went ahead and set Copy Local = True for those assemblies just to be doubly sure they're around... but I'm still stuck with this annoying compile error.
I think this boils down to how things are referenced in your solution. So I'm going to take a couple guesses.
It sounds like your DLL references the DAL as an assembly instead of as a project reference.
During compile time Visual Studio copies everything it thinks is necessary to the projects BIN directory. If you reference an external DLL (DAL) then it will copy that DLL only to your BLL's BIN directory.
What you need to do is get it to copy the SMO assemblies as well OR have those SMO assemblies available through the GAC. Personally, I don't like GAC'ing things, so I'll ignore that.
There are three ways of doing this. The easiest is to simply add a reference to those other assemblies to your BLL. Obviously that's not what you want.
The second way is to reference the DAL project as a project reference. This will allow Visual Studio to detect the extra dependencies and copy them accordingly. This is also not exactly what you want as well.
The third way is to copy them as part of a build step. Right click on your BLL project and go to Build Events. In the Pre-build event command line put in the commands to copy the necessary SMO files to your BLL projects BIN directory.
You'll have to do this again for the main service project as well.
It's depressing to answer your own question with a mea culpa, "I'm an idiot"... but, well, I'm an idiot:
In Utilities there was an overload for the offending method which did contain an Smo.Server parameter. I removed that overload (an artifact from testing before refactoring) and voila, problem solved/idiocy confirmed! The interesting thing I learned here is that using the other methods of the Utilities class, which did not have overloads containing Smo objects, was absolutely fine, meaning even with a function in the Utilities class which required an Smo object for a parameter, as long as I didn't call that method or one of its overloads, the references resolved perfectly without a hitch. The new question I have, is why? Why does that overload's existence matter for reference resolution if I call another version of that function from a project higher in the dependency chain? Is there some internal loop where it goes over all versions of a function checking references if any version has been called...
Scenario
Visual Studio 2010
Silverlight 4
Entity Framework
Self-tracking entities
Problem
On the server side, we have generated entity objects using Entity Framework model. We have used self tracking T4 templates to generate the entities. These entities are shared and can be used from the client side (Silverlight 4 project).
But when we try to add a new Web Service reference, the proxy generator don't work. The reference.cs file is empty. We have checked the option 'Reuse Types' in the configuration of the Web Reference. We have checked the assemblies that will be shared (entity assemblies only).
We have tried to remove every (IsReference=true) from DataContract attributes of the entities but it did not work.
Any idea or workaround?
Unchecking the "Reuse Types" worked for me. The code generator walks the object graph of dependencies and if it encounters any problem, like a reference not found, then it blows up and doesn't produce any code in the reference.cs.
This can occur when the assembly your are trying to share is compiled against a higher .NET platform.
For example if your project is targeting .NET 3.5 and the assembly is compiled against 4.0 this will happen.
You have checked the option Reuse Types? Try uncheck the option Reuse Types