diff --git a/src/EFTools/EntityDesign/EntityDesign.csproj b/src/EFTools/EntityDesign/EntityDesign.csproj index 9c3150f689..1a65a8db41 100644 --- a/src/EFTools/EntityDesign/EntityDesign.csproj +++ b/src/EFTools/EntityDesign/EntityDesign.csproj @@ -71,6 +71,7 @@ + diff --git a/src/EFTools/EntityDesign/VisualStudio/ExecutorWrapper.cs b/src/EFTools/EntityDesign/VisualStudio/ExecutorWrapper.cs index 6a21ab6b32..cefe5223f0 100644 --- a/src/EFTools/EntityDesign/VisualStudio/ExecutorWrapper.cs +++ b/src/EFTools/EntityDesign/VisualStudio/ExecutorWrapper.cs @@ -61,16 +61,7 @@ public string GetProviderServices(string invariantName) { Debug.Assert(!string.IsNullOrWhiteSpace(invariantName), "invariantName is null or empty."); - string providerServicesTypeName = null; - try - { - providerServicesTypeName = Invoke("GetProviderServices", new[] { invariantName }); - } - catch - { - } - - return providerServicesTypeName; + return Invoke("GetProviderServices", new[] { invariantName }); } private TResult Invoke(string operation, IEnumerable args, object anonymousArguments = null) diff --git a/src/EFTools/EntityDesign/VisualStudio/VsUtils.cs b/src/EFTools/EntityDesign/VisualStudio/VsUtils.cs index e19a316bce..1263b9dd77 100644 --- a/src/EFTools/EntityDesign/VisualStudio/VsUtils.cs +++ b/src/EFTools/EntityDesign/VisualStudio/VsUtils.cs @@ -4,9 +4,11 @@ namespace Microsoft.Data.Entity.Design.VisualStudio { using System; using System.Collections.Generic; + using System.Configuration; using System.Data.Common; using System.Data.Entity.Core.Common; using System.Data.Entity.Infrastructure.DependencyResolution; + using System.Data.Entity.Infrastructure.Design; using System.Data.Entity.SqlServer; using System.Data.SqlClient; using System.Diagnostics; @@ -38,6 +40,7 @@ namespace Microsoft.Data.Entity.Design.VisualStudio using VSLangProj80; using VsWebSite; using VsWebSite90; + using ConfigurationManager = System.Configuration.ConfigurationManager; using Constants = EnvDTE.Constants; using PrjKind = VSLangProj.PrjKind; using Resources = Microsoft.Data.Entity.Design.Resources; @@ -374,13 +377,13 @@ private static void LogStandardTask(string message, string filePath, int lineNum { ErrorListHelper.MiscErrorList.AddItem( new ErrorTask - { - Document = filePath, - Text = message, - Line = lineNumber, - Column = columnNumber, - ErrorCategory = category - }); + { + Document = filePath, + Text = message, + Line = lineNumber, + Column = columnNumber, + ErrorCategory = category + }); } // @@ -2196,14 +2199,34 @@ private static string GetModernProviderTypeNameFromProject( providerServicesTypeName = context.Executor.GetProviderServices(invariantName); } } - catch (Exception ex) + catch { - Debug.Fail(ex.ToString()); + try + { + providerServicesTypeName = GetProviderServicesFromConfig(invariantName, project, serviceProvider); + } + catch (Exception ex) + { + Debug.Fail(ex.ToString()); + } } return providerServicesTypeName; } + private static string GetProviderServicesFromConfig( + string invariantName, + Project project, + IServiceProvider serviceProvider) + { + var configurationFile = GetProjectConfigurationFile(project, serviceProvider); + var configuration = ConfigurationManager.OpenMappedExeConfiguration( + new ExeConfigurationFileMap { ExeConfigFilename = configurationFile }, + ConfigurationUserLevel.None); + + return new AppConfigReader(configuration).GetProviderServices(invariantName); + } + internal static string GetProviderManifestTokenConnected( IDbDependencyResolver resolver, string providerInvariantName, string providerConnectionString) { diff --git a/src/EntityFramework/EntityFramework.csproj b/src/EntityFramework/EntityFramework.csproj index 1cb2c6acb5..9a72aac39b 100644 --- a/src/EntityFramework/EntityFramework.csproj +++ b/src/EntityFramework/EntityFramework.csproj @@ -252,6 +252,7 @@ + diff --git a/src/EntityFramework/Infrastructure/Design/AppConfigReader.cs b/src/EntityFramework/Infrastructure/Design/AppConfigReader.cs new file mode 100644 index 0000000000..7805583970 --- /dev/null +++ b/src/EntityFramework/Infrastructure/Design/AppConfigReader.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +namespace System.Data.Entity.Infrastructure.Design +{ + using System.Configuration; + using System.Data.Entity.Internal; + using System.Data.Entity.Internal.ConfigFile; + using System.Data.Entity.Utilities; + using System.Linq; + + /// + /// Provides utility methods for reading from an App.config or Web.config file. + /// + public class AppConfigReader + { + private readonly Configuration _configuration; + + /// + /// Initializes a new instance of . + /// + /// The configuration to read from. + public AppConfigReader(Configuration configuration) + { + Check.NotNull(configuration, "configuration"); + + _configuration = configuration; + } + + /// + /// Gets the specified provider services from the configuration. + /// + /// The invariant name of the provider services. + /// The provider services type name, or null if not found. + public string GetProviderServices(string invariantName) + { + var providers = ((EntityFrameworkSection)_configuration.GetSection(AppConfig.EFSectionName)) + .Providers.Cast(); + + return (from p in providers + where p.InvariantName == invariantName + select p.ProviderTypeName) + .FirstOrDefault(); + } + } +} diff --git a/src/EntityFramework/Infrastructure/Design/Executor.cs b/src/EntityFramework/Infrastructure/Design/Executor.cs index ed55735f1d..f4cb53c941 100644 --- a/src/EntityFramework/Infrastructure/Design/Executor.cs +++ b/src/EntityFramework/Infrastructure/Design/Executor.cs @@ -43,18 +43,23 @@ internal virtual string GetProviderServicesInternal(string invariantName) { DebugCheck.NotEmpty(invariantName); - string providerServicesTypeName = null; + DbConfiguration.LoadConfiguration(_assembly); + var dependencyResolver = DbConfiguration.DependencyResolver; + + DbProviderServices providerServices = null; try { - DbConfiguration.LoadConfiguration(_assembly); - var providerServices = DbConfiguration.DependencyResolver.GetService(invariantName); - providerServicesTypeName = providerServices.GetType().AssemblyQualifiedName; + providerServices = dependencyResolver.GetService(invariantName); } catch { } + if (providerServices == null) + { + return null; + } - return providerServicesTypeName; + return providerServices.GetType().AssemblyQualifiedName; } // diff --git a/src/EntityFramework/Internal/AppConfig.cs b/src/EntityFramework/Internal/AppConfig.cs index 1cfb480a75..578a50d0c7 100644 --- a/src/EntityFramework/Internal/AppConfig.cs +++ b/src/EntityFramework/Internal/AppConfig.cs @@ -18,7 +18,7 @@ namespace System.Data.Entity.Internal // internal class AppConfig { - private const string EFSectionName = "entityFramework"; + public const string EFSectionName = "entityFramework"; private static readonly AppConfig _defaultInstance = new AppConfig(); private readonly KeyValueConfigurationCollection _appSettings; diff --git a/test/EFTools/UnitTests/EntityDesign/VisualStudio/ExecutorWrapperTests.cs b/test/EFTools/UnitTests/EntityDesign/VisualStudio/ExecutorWrapperTests.cs index fd5378d66a..54cd207b93 100644 --- a/test/EFTools/UnitTests/EntityDesign/VisualStudio/ExecutorWrapperTests.cs +++ b/test/EFTools/UnitTests/EntityDesign/VisualStudio/ExecutorWrapperTests.cs @@ -46,48 +46,5 @@ public void GetProviderServices_returns_null_when_unknown() AppDomain.Unload(domain); } } - - [Fact] - public void GetProviderServices_returns_null_when_no_project_assembly() - { - var domain = AppDomain.CreateDomain("ExecutorWrapperTests", null, AppDomain.CurrentDomain.SetupInformation); - try - { - var executor = new ExecutorWrapper( - domain, - "UnknownProject.dll"); - - Assert.Null(executor.GetProviderServices("System.Data.SqlClient")); - } - finally - { - AppDomain.Unload(domain); - } - } - - [Fact] - public void GetProviderServices_returns_null_when_no_EntityFramework_assembly() - { - var domain = AppDomain.CreateDomain( - "ExecutorWrapperTests", - null, - new AppDomainSetup - { - // NOTE: This will cause assembly resolution for EntityFramework to fail - ApplicationBase = Path.GetTempPath() - }); - try - { - var executor = new ExecutorWrapper( - domain, - Path.GetFileName(GetType().Assembly.CodeBase)); - - Assert.Null(executor.GetProviderServices("System.Data.SqlClient")); - } - finally - { - AppDomain.Unload(domain); - } - } } } diff --git a/test/EntityFramework/UnitTests/Infrastructure/Design/AppConfigReaderTests.cs b/test/EntityFramework/UnitTests/Infrastructure/Design/AppConfigReaderTests.cs new file mode 100644 index 0000000000..49dd4944f0 --- /dev/null +++ b/test/EntityFramework/UnitTests/Infrastructure/Design/AppConfigReaderTests.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +namespace System.Data.Entity.Infrastructure.Design +{ + using System.Configuration; + using System.IO; + using Xunit; + + public class AppConfigReaderTests + { + [Fact] + public void Ctor_validates_parameter() + { + var ex = Assert.Throws(() => new AppConfigReader(null)); + + Assert.Equal("configuration", ex.ParamName); + } + + [Fact] + public void GetProviderServices_returns_provider_when_exists() + { + var reader = new AppConfigReader( + CreateConfig("")); + + var provider = reader.GetProviderServices("My.Invariant1"); + + Assert.Equal("MyProvider1", provider); + } + + [Fact] + public void GetProviderServices_returns_null_when_not_exists() + { + var reader = new AppConfigReader( + CreateConfig("")); + + var provider = reader.GetProviderServices("My.Invariant2"); + + Assert.Null(provider); + } + + private static Configuration CreateConfig(string providers) + { + var file = Path.GetTempFileName(); + File.WriteAllText( + file, + @" + + +
+ + + + " + providers + @" + + + "); + + return ConfigurationManager.OpenMappedExeConfiguration( + new ExeConfigurationFileMap { ExeConfigFilename = file }, + ConfigurationUserLevel.None); + } + } +} diff --git a/test/EntityFramework/UnitTests/UnitTests.csproj b/test/EntityFramework/UnitTests/UnitTests.csproj index 7bf0a68204..964d90f49e 100644 --- a/test/EntityFramework/UnitTests/UnitTests.csproj +++ b/test/EntityFramework/UnitTests/UnitTests.csproj @@ -312,6 +312,7 @@ +