PostSharp.Samples.Xaml + EntityFramework - entity-framework

While converting PostSharp.Samples.Xaml sample to use EntityFramework, I am encountering "k__BackingField" problem mentioned in PostSharp inserting k__Backing Field into Entity Class, causing Database generation to fail. Can you show me how to use the proposed solution "Use MulticastAttributeUsageAttribute.AttributeTargets to restrict it to properties." without losing PostSharp's INotifyPropertyChanged? I am trying to persuade the stakeholders by showcasing both EF and PS.
Here's the change to AddressModel.cs
using System;
using System.ComponentModel;
using System.Text;
using PostSharp.Patterns.Contracts;
using PostSharp.Patterns.Model;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PostSharp.Samples.Xaml
{
public class AddressModel : ModelBase
{
public int AddressId { get; set; }
[DisplayName("Address Line 1")]
[Patterns.Contracts.Required]
public string Line1 { get; set; }
[DisplayName("Address Line 2")]
public string Line2 { get; set; }
[Patterns.Contracts.Required]
public string Town { get; set; }
public string Country { get; set; }
public DateTime Expiration { get; set; }
[IgnoreAutoChangeNotification]
public TimeSpan Lifetime => DateTime.Now - Expiration;
[SafeForDependencyAnalysis]
public string FullAddress
{
get
{
var stringBuilder = new StringBuilder();
if (Line1 != null) stringBuilder.Append(Line1);
if (Line2 != null)
{
if (stringBuilder.Length > 0) stringBuilder.Append("; ");
stringBuilder.Append(Line2);
}
if (Town != null)
{
if (stringBuilder.Length > 0) stringBuilder.Append("; ");
stringBuilder.Append(Town);
}
if (Country != null)
{
if (stringBuilder.Length > 0) stringBuilder.Append("; ");
stringBuilder.Append(Country);
}
return stringBuilder.ToString();
}
}
[ForeignKey("AddressId")]
[Parent]
public virtual CustomerModel Person { get; set; }
}
}
app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="PostSharp" publicKeyToken="b13fd38b8f9c99d7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.37.0" newVersion="5.0.37.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
CustomerModel.cs
using System.IO;
using System.Threading;
using PostSharp.Patterns.Collections;
using PostSharp.Patterns.Contracts;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Threading;
using System;
using System.ComponentModel.DataAnnotations;
using PostSharp.Extensibility;
namespace PostSharp.Samples.Xaml
{
public class CustomerModel : ModelBase
{
[Key]
public int CustomerId { get; set; }
public string FirstName { get; set; }
[Patterns.Contracts.Required]
public string LastName { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
[Child]
public AdvisableCollection<AddressModel> Addresses { get; set; }
[Reference]
public AddressModel PrincipalAddress { get; set; }
[Reader]
public void Save(string path)
{
using (var stringWriter = new StreamWriter(path))
{
// We need to make sure the object graph is not being modified when we save,
// and this is ensured by [ReaderWriterSynchronized] in ModelBase.
stringWriter.WriteLine($"UserID: {CustomerId}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"FirstName: {FirstName}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"LastName: {LastName}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"Phone: {Phone}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"Mobile: {Mobile}");
//Thread.Sleep(1000);
stringWriter.WriteLine($"Email: {Email}");
//Thread.Sleep(1000);
foreach (var address in Addresses)
{
//Thread.Sleep(1000);
if (address == PrincipalAddress)
stringWriter.WriteLine($"Principal address: {address}");
else
stringWriter.WriteLine($"Secondary address: {address}");
}
try
{
using (var ctx = new EFContext())
{
ctx.Person.Add(this);
ctx.SaveChanges();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
MainWindow.xaml
<Window x:Class="PostSharp.Samples.Xaml.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xaml="clr-namespace:PostSharp.Samples.Xaml"
xmlns:controls="clr-namespace:PostSharp.Patterns.Model.Controls;assembly=PostSharp.Patterns.Xaml"
Title="Contact Form" Height="352.584" Width="352.753"
x:Name="Window">
<Window.DataContext>
<xaml:CustomerViewModel />
</Window.DataContext>
<DockPanel>
<ToolBarTray DockPanel.Dock="Top">
<ToolBar>
<Button Name="SaveButton" Command="{Binding ElementName=Window, Path=SaveCommand}">Save</Button>
<controls:UndoButton />
<controls:RedoButton />
</ToolBar>
</ToolBarTray>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="29*" />
<ColumnDefinition Width="316*" />
</Grid.ColumnDefinitions>
<Label Content="First Name:" HorizontalAlignment="Left" Margin="10,62,0,0" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,62,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.FirstName, ValidatesOnExceptions=True}" VerticalAlignment="Top"
Width="189" Grid.Column="1" />
<Label Content="Last Name:" HorizontalAlignment="Left" Margin="10,88,0,0" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,92,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.LastName, ValidatesOnExceptions=True}" VerticalAlignment="Top"
Width="189" Grid.Column="1" />
<Label Content="Principal Address:" HorizontalAlignment="Left" Margin="10,119,0,0" VerticalAlignment="Top"
RenderTransformOrigin="-0.105,-0.462" Grid.ColumnSpan="2" />
<ComboBox HorizontalAlignment="Left" Margin="97.846,120,0,0" VerticalAlignment="Top" Width="189"
ItemsSource="{Binding Path=Customer.Addresses}"
SelectedValue="{Binding Path=Customer.PrincipalAddress}" DisplayMemberPath="FullAddress"
Grid.Column="1" />
<xaml:FancyTextBlock HorizontalAlignment="Left" Margin="10,15,0,0" Text="{Binding Path=FullName}"
VerticalAlignment="Top" Width="214" Grid.ColumnSpan="2" />
<Label Content="Line1:" HorizontalAlignment="Left" Margin="11.846,150,0,0" VerticalAlignment="Top"
Grid.Column="1" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,154,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.PrincipalAddress.Line1, ValidatesOnExceptions=True}"
VerticalAlignment="Top" Width="189" Grid.Column="1" />
<Label Content="Town:" HorizontalAlignment="Left" Margin="12.846,176,0,0" VerticalAlignment="Top"
Grid.Column="1" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,182,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.PrincipalAddress.Town, ValidatesOnExceptions=True}"
VerticalAlignment="Top" Width="189" Grid.Column="1" />
<Label Content="User Id:" HorizontalAlignment="Left" Margin="11.846,210,0,0" VerticalAlignment="Top"
Grid.ColumnSpan="2" />
<TextBox HorizontalAlignment="Left" Height="23" Margin="97.846,210,0,0" TextWrapping="Wrap"
Text="{Binding Path=Customer.UserID, ValidatesOnExceptions=True}" VerticalAlignment="Top"
Width="189" Grid.Column="1" />
</Grid>
</DockPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Input;
using Microsoft.Win32;
using PostSharp.Patterns.Collections;
using PostSharp.Patterns.Model;
using PostSharp.Patterns.Recording;
using PostSharp.Patterns.Threading;
using PostSharp.Patterns.Xaml;
namespace PostSharp.Samples.Xaml
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
[NotifyPropertyChanged]
public partial class MainWindow : Window
{
/* private readonly */
public readonly CustomerModel customer = new CustomerModel
{
Email = "2",
Mobile = "3",
Phone = "4",
CustomerId = 1,
FirstName = "Jan",
LastName = "Novak",
Addresses = new AdvisableCollection<AddressModel>
{
new AddressModel
{
Line1 = "Saldova 1G",
Town = "Prague",
Country = "USA"
},
new AddressModel
{
Line1 = "Tyrsova 25",
Town = "Brno",
Country = "USA"
},
new AddressModel
{
Line1 = "Pivorarka 154",
Town = "Pilsen",
Country = "USA"
}
}
};
private readonly Recorder recorder;
public MainWindow()
{
// We need to have a local reference for [NotifyPropertyChanged] to work.
recorder = RecordingServices.DefaultRecorder;
InitializeComponent();
// Register our custom operation formatter.
RecordingServices.OperationFormatter = new MyOperationFormatter(RecordingServices.OperationFormatter);
// Create initial data.
var customerViewModel = new CustomerViewModel {Customer = customer};
customerViewModel.Customer.PrincipalAddress = customerViewModel.Customer.Addresses[0];
// Clear the initialization steps from the recorder.
recorder.Clear();
DataContext = customerViewModel;
}
[Command]
public ICommand SaveCommand { get; private set; }
public bool CanExecuteSave => recorder.UndoOperations.Count > 0;
private void ExecuteSave()
{
var openFileDialog = new SaveFileDialog();
if (openFileDialog.ShowDialog().GetValueOrDefault())
Save(openFileDialog.FileName);
}
[Background]
[DisableUI]
private void Save(string path)
{
customer.Save(path);
}
}
}
packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
<package id="PostSharp" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Aggregation" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Aggregation.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Common" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Common.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Model" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Model.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Threading" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Threading.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Patterns.Xaml" version="5.0.40" targetFramework="net461" developmentDependency="true" />
<package id="PostSharp.Patterns.Xaml.Redist" version="5.0.40" targetFramework="net461" />
<package id="PostSharp.Redist" version="5.0.40" targetFramework="net461" />
</packages>
PostSharp.Samples.Xaml.csproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\PostSharp.5.0.40\build\PostSharp.props" Condition="Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B10B8456-75F7-4D68-9775-CC87517B07B6}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PostSharp.Samples.Xaml</RootNamespace>
<AssemblyName>PostSharp.Samples.Xaml</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>6</LangVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp, Version=5.0.40.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7">
<HintPath>..\..\packages\PostSharp.Redist.5.0.40\lib\net35-client\PostSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Aggregation">
<HintPath>..\..\packages\PostSharp.Patterns.Aggregation.Redist.5.0.40\lib\net45\PostSharp.Patterns.Aggregation.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Common">
<HintPath>..\..\packages\PostSharp.Patterns.Common.Redist.5.0.40\lib\net46\PostSharp.Patterns.Common.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Model">
<HintPath>..\..\packages\PostSharp.Patterns.Model.Redist.5.0.40\lib\net40\PostSharp.Patterns.Model.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Threading">
<HintPath>..\..\packages\PostSharp.Patterns.Threading.Redist.5.0.40\lib\net45\PostSharp.Patterns.Threading.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PostSharp.Patterns.Xaml">
<HintPath>..\..\packages\PostSharp.Patterns.Xaml.Redist.5.0.40\lib\net40\PostSharp.Patterns.Xaml.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="FancyTextBlock.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="AddressModel.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="CustomerModel.cs" />
<Compile Include="CustomerViewModel.cs" />
<Compile Include="DisableUIAttribute.cs" />
<Compile Include="EFContext.cs" />
<Compile Include="FancyTextBlock.xaml.cs">
<DependentUpon>FancyTextBlock.xaml</DependentUpon>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="ModelBase.cs" />
<Compile Include="MyOperationFormatter.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
<None Include="README.md" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.40\build\PostSharp.props'))" />
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.40\build\PostSharp.targets'))" />
</Target>
<Import Project="..\..\packages\PostSharp.5.0.40\build\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp.5.0.40\build\PostSharp.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
Everything else remain the same, and you should be able to build it and see the exception in CustomerModel.cs line#80 when you change any field in the app and try to save.
You get following ex.Message;
One or more validation errors were detected during model generation:
PostSharp.Samples.Xaml.AddressModel: : EntityType 'AddressModel' has no key defined. Define the key for this EntityType.
<Person>k__BackingField: Name: The specified name is not allowed: '<Person>k__BackingField'.
PostSharp.Samples.Xaml.AddressModel_<Person>k__BackingField: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField'.
AddressModel_<Person>k__BackingField_Source: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField_Source'.
AddressModel_<Person>k__BackingField_Target: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField_Target'.
AddressModels: EntityType: EntitySet 'AddressModels' is based on type 'AddressModel' that has no keys defined.
AddressModel_<Person>k__BackingField: Name: The specified name is not allowed: 'AddressModel_<Person>k__BackingField'.
A new file that was not in the original sample solution, EFContext.cs:
using System.Data.Entity;
namespace PostSharp.Samples.Xaml
{
public class EFContext :DbContext
{
public DbSet<CustomerModel> Person { get; set; }
}
}

You can use OnModelCreating and modelBuilder.Entity<T>.Ignore(x => x.Property) in runtime to ignore the failing property programmatically. The following demonstrates changes to EFContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
IgnorePostSharpProperties<CustomerModel>(modelBuilder);
IgnorePostSharpProperties<AddressModel>(modelBuilder);
base.OnModelCreating(modelBuilder);
}
public void IgnorePostSharpProperties<T>(DbModelBuilder modelBuilder)
where T : class
{
foreach (PropertyInfo property in typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance))
{
// We don't want properties that are compiler-generated with a special PostSharp name.
if (!property.IsDefined(typeof(CompilerGeneratedAttribute), false) || !property.Name.Contains("<"))
continue;
ParameterExpression paramExpression = Expression.Parameter(typeof(T));
Expression expression = Expression.Lambda(
Expression.Property(paramExpression, property.Name),
paramExpression
);
EntityTypeConfiguration<T> entityTypeConfig = modelBuilder.Entity<T>();
MethodInfo ignoreMethodDefinition = entityTypeConfig.GetType().GetMethod("Ignore", BindingFlags.Public | BindingFlags.Instance);
MethodInfo ignoreMethodInstance = ignoreMethodDefinition.MakeGenericMethod(property.PropertyType);
// Ignore the property.
ignoreMethodInstance.Invoke(entityTypeConfig, new object[] {expression});
}
}

Related

Flyout Page not responding

I'm starting understanding .Net MAUI with an online video.
I'm trying to customize a page with 3 buttons, 1 for a counter, 1 for a second page and 1 for a flyoutpage.
Counter and second page are ok, flyout page doesn't display but force the App to exit.
My code for the button that calls the flyout page is this, located in the MainPage.xml.cs :
private void FlyClicked(object sender, EventArgs e)
{
Navigation.PushAsync(new Flyout1());
}
Can anybody explain me the reason of this ?
Many Thanks
According to your description, the Flyout1 should be a FlyoutPage. You can refer to the code below on how to create a FlyoutPage. I test it and it can display it.
Flyout1:
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<FlyoutPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAppDualScreen.Flyout1"
xmlns:local="clr-namespace:MauiAppDualScreen"
>
<FlyoutPage.Flyout>
<local:FlyoutMenuPage x:Name="flyoutPage" />
</FlyoutPage.Flyout>
<FlyoutPage.Detail>
<NavigationPage>
<x:Arguments>
<local:MainPage />
</x:Arguments>
</NavigationPage>
</FlyoutPage.Detail>
</FlyoutPage>
Code-behind:
public partial class Flyout1 : FlyoutPage
{
      public Flyout1()
      {
            InitializeComponent();
}
}
The following example shows the definition of the FlyoutMenuPage object, which is of type ContentPage:
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAppDualScreen.FlyoutMenuPage"
xmlns:local="clr-namespace:MauiAppDualScreen"
Title="FlyoutMenuPage">
<CollectionView x:Name="collectionView"
x:FieldModifier="public"
SelectionMode="Single">
<CollectionView.ItemsSource>
<x:Array Type="{x:Type local:FlyoutPageItem}">
<local:FlyoutPageItem Title="Contacts"
IconSource="dotnet_bot.png"
TargetType="{x:Type local:MainPage}" />
<local:FlyoutPageItem Title="TodoList"
IconSource="dotnet_bot.png"
TargetType="{x:Type local:MainPage}" />
<local:FlyoutPageItem Title="Reminders"
IconSource="dotnet_bot.png"
TargetType="{x:Type local:MainPage}" />
</x:Array>
</CollectionView.ItemsSource>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1"
Margin="20,0"
Text="{Binding Title}"
FontSize="20"
FontAttributes="Bold"
VerticalOptions="Center" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
Code-behind:
public partial class FlyoutMenuPage : ContentPage
{
      public FlyoutMenuPage()
      {
            InitializeComponent();
      }
}
The flyout page consists of a CollectionView that's populated with data by setting its ItemsSource property to an array of FlyoutPageItem objects. The following example shows the definition of the FlyoutPageItem class:
public class FlyoutPageItem
{
public string Title { get; set; }
public string IconSource { get; set; }
public Type TargetType { get; set; }
}

Adding a new record to DB, key is always zero

I have an existing App written using Microsoft Visual C++ 2017, ASP.NET, MVC 5.2.7.0, Entity Framework Version=5, DB is SQL Server. When I add a new record to my DB, the key (ParkID) that results is a zero and when I try and save the change. I get an error.
Cannot insert the value NULL into column 'ParkID', table 'N_CWBFM-20170818.dbo.Park'; column does not allow nulls. INSERT fails.
The database N_CWBFM-20170818 was downloaded from the HOST where my app runs.
Confession, this is a hobby, so I may not use the correct terminology and translating other ways of adding data to a DB to the method I am using.
Model
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace CWBFM.Models
{
public class Park
{
[Key]
public int ParkID { get; set; }
public bool ParkChangePending { get; set; } // change pending true/false
public int ParkChangeCount { get; set; } // Count the number of changes to this record
public int ParkPrevRec { get; set; } // points backwards to the previous version
public int ParkNextRec { get; set; } // ID of previous record
Omitted
DB Context
using CWBFM.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace CWBFM.DAL
{
public class CWBFMContext : DbContext
{
public DbSet<Park> Parks { get; set; }
public DbSet<Photo> Photo { get; set; }
public DbSet<StateFilter> StateFilters { get; set; }
Omitted
Controller
using System;
using System.Data;
using System.Linq;
using System.Web.Mvc;
using CWBFM.Models;
using CWBFM.DAL;
namespace CWBFM.Controllers
{
public class ParkController : BaseController
{
private CWBFMContext db = new CWBFMContext();
Omitted
// POST: /Park/Create
[HttpPost]
[Authorize]
public ActionResult ParkCreate(Park park)
{
setYesNo(); //set the values for the dropdown box (Yes, No, Unknown)
if (ModelState.IsValid)
{
park.ParkChangePending = false;
park.ParkChangeCount = 0;
park.ParkDateCreated = DateTime.Now;
park.ParkDateChange = DateTime.Now;
park.ParkCreatedBy = #User.Identity.Name;
park.ParkChangedBy = #User.Identity.Name;
park.ParkStatus = "N";
db.Parks.Add(park);
int stop = park.ParkID;
db.SaveChanges();
park.ParkRecID = "Park" + park.ParkID.ToString();
db.SaveChanges();
return RedirectToAction("ParkDetails", new { id=park.ParkID });
}
return View(park);
}
Config
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<!-- <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="Telerik.Web.Mvc.UI" />
</namespaces>
</pages>
<httpRuntime targetFramework="4.6.1" maxRequestLength="20971520" />
<!-- This will handle requests up to 20MB -->
<profile inherits="CWBFM.Models.MyUserProfile" defaultProvider="DefaultProvider">
<providers>
<clear />
<add name="DefaultProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>
<!--<profile defaultProvider="DefaultProfileProvider">
<providers>
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>-->
<membership defaultProvider="DefaultMembershipProvider">
<providers>
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="DefaultRoleProvider">
<providers>
<add connectionStringName="DefaultConnection" applicationName="/" name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</providers>
</roleManager>
<!--
If you are deploying to a cloud environment that has multiple web server instances,
you should change session state mode from "InProc" to "Custom". In addition,
change the connection string named "DefaultConnection" to connect to an instance
of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express.
-->
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
<httpHandlers>
<add verb="GET,HEAD" path="asset.axd" validate="false" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc" />
</httpHandlers>
<httpModules>
<add name="CompilableFileModule" type="SassAndCoffee.CompilableFileModule" />
</httpModules>
</system.web>
<system.webServer>
<security>
<requestFiltering>
<!-- This will handle requests up to 1024MB (1GB) -->
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="asset" />
<add name="asset" preCondition="integratedMode" verb="GET,HEAD" path="asset.axd" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" /><remove name="OPTIONSVerbHandler" /><remove name="TRACEVerbHandler" /><add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /></handlers>
<modules>
<remove name="CompilableFileModule" />
<add name="CompilableFileModule" type="SassAndCoffee.CompilableFileModule" />
</modules>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
<connectionStrings>
It dies on the save (db.SaveChanges();). A breakpoint at int stop = park.ParkID; shows that the ParkID is zero.
ParkID = 0
I have looked at several proposed solutions, but just can’t find one that works. Any suggestions. Could I have missed an update in my config when I changed to EF 5?
This can occur if the database was set up without an Identity column set on the PK, but EF will automatically expect an identity column on keys named "Id" or with the "Id" suffix on the class name. (I.e. Park.ParkId) If the DB is not actually set up to use an Identity but EF is configured for an Identity column (DatabaseGeneratedOption.Identity) the resulting insert statements will not include the ParkId column, resulting in a #null failure in the database.
I generally recommend being explicit with configuration rather than relying on EF's conventions for behaviour:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ParkId { get; set; }
If you expect the new records to be given a PK value automatically by the database then update the database schema to mark these PKs as Identity columns. If your schema is code-first and generating Migrations then there should be a way to apply a migration to update the PKs to identity columns. Otherwise simply make the change within SSMS.
If instead you want to provide PKs from your code, (such as part of data imports from other data sources) then you need to configure EF to not treat the PK as an Identity.
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ParkId { get; set; }

Datagrid not showing data even though its boudn

I have a problem with my MVVM Light implementation where I have my WPF Toolkit DataGrid and Data context bound to the correct object but no data is showing up. Can someone tell me what I'm doing wrong?
Here is my code:
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private C.Wsi.ClientSession privateSession;
private ObservableCollection<CashAccount> _cashaccounts;
public ObservableCollection<CashAccount> CashAccounts
{
get { return _cashaccounts; }
set
{
if (_cashaccounts.Equals(value))
{
return;
}
_cashaccounts = value;
RaisePropertyChanged("CashAccounts");
}
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
_cashaccounts = new ObservableCollection<CashAccount>();
// Subscribe to CollectionChanged event
_cashaccounts.CollectionChanged += OnCashAccountListChanged;
logger.Info("----- Start -----");
// Code runs "for real"
Cs.Helper.Session session = new Session();
privateSession = session.getSession();
logger.Info("Private Session: " + privateSession.GetHashCode());
logger.Info("...Connected.....");
Cs.Helper.ResultSet results = new ResultSet();
PositionBean[] pos = results.getPositions(privateSession);
logger.Info("Positions returned: " + pos.Length);
SecurityBean[] secs = results.getSecurities(privateSession);
logger.Info("Securities returned: " + secs.Length);
ArrayBuilder ab = new ArrayBuilder(pos, secs);
CashAccount c = new CashAccount();
c.qtySod = 100.00;
c.name = "Hi";
c.account = "Acct1";
c.cashAmount = 67.00;
_cashaccounts.Add(c);
RaisePropertyChanged("CashAccounts");
//this._cashaccounts=ab.joinPositionSecurities();
}
}
void OnCashAccountListChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
}
////public override void Cleanup()
////{
//// // Clean up if needed
//// base.Cleanup();
////}
}
MainWindow.xaml
<Window x:Class="CreditSuisse.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CreditSuisse.Helper"
xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
mc:Ignorable="d"
Height="301"
Width="520"
Title="Credit Suisse - Custodial Cash Application"
DataContext="{Binding Path=Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
<local:VisibilityConverter x:Key="VisibilityConverter" />
<!-- DataGrid Background -->
<LinearGradientBrush x:Key="BlueLightGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFEAF3FF"/>
<GradientStop Offset="0.654" Color="#FFC0DEFF"/>
<GradientStop Offset="1" Color="#FFC0D9FB"/>
</LinearGradientBrush>
<!-- DatGrid style -->
<Style TargetType="{x:Type dg:DataGrid}">
<Setter Property="Margin" Value="5" />
<Setter Property="Background" Value="{StaticResource BlueLightGradientBrush}" />
<Setter Property="BorderBrush" Value="#FFA6CCF2" />
<Setter Property="RowBackground" Value="White" />
<Setter Property="AlternatingRowBackground" Value="#FDFFD0" />
<Setter Property="HorizontalGridLinesBrush" Value="Transparent" />
<Setter Property="VerticalGridLinesBrush" Value="#FFD3D0" />
<Setter Property="RowHeaderWidth" Value="0" />
</Style>
<!-- Enable rows as drop targets -->
<Style TargetType="{x:Type dg:DataGridRow}">
<Setter Property="AllowDrop" Value="True" />
</Style>
</ResourceDictionary>
</Window.Resources>
<dg:DataGrid DataContext="{Binding MainViewModel}" ItemsSource="{Binding CashAccounts}">
Margin="5" AutoGenerateColumns="True" HorizontalScrollBarVisibility="False">
<dg:DataGrid.Columns>
<dg:DataGridTextColumn Binding="{Binding account}" Header="Account Code" />
<dg:DataGridTextColumn Binding="{Binding name}" Header="Security Name" />
<dg:DataGridTextColumn Binding="{Binding cashAmount}" Header="Quantity Start of Day" />
<dg:DataGridTextColumn Binding="{Binding price}" Header="Cash Delta (Price Delta)" />
<dg:DataGridTemplateColumn Header="Action">
<dg:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Get" Visibility="{Binding cashChanged, Converter={StaticResource VisibilityConverter}}" Background="Red" />
</DataTemplate>
</dg:DataGridTemplateColumn.CellTemplate>
</dg:DataGridTemplateColumn>
</dg:DataGrid.Columns>
</dg:DataGrid>
When you do DataContext="{Binding Path=Main, Source={StaticResource Locator}}" in your Window and after DataContext="{Binding MainViewModel}" in the Datagrid, WPF tries to bind to a property named MainViewModel on your MainViewModel class which will fail. You can confirm this by looking for the binding error in the Output window in VS.
Just remove DataContext="{Binding MainViewModel}" from the DataGrid and it should work.
EDIT:
There is an extra closing > at the end of the first line in your XAML:
<dg:DataGrid DataContext="{Binding MainViewModel}" ItemsSource="{Binding CashAccounts}">
Margin="5" AutoGenerateColumns="True" HorizontalScrollBarVisibility="False">
It should be:
<dg:DataGrid DataContext="{Binding MainViewModel}" ItemsSource="{Binding CashAccounts}"
Margin="5" AutoGenerateColumns="True" HorizontalScrollBarVisibility="Disabled">
Note: False is not a valid value for HorizontalScrollBarVisibility it supports Auto, Disabled, Hidden, Visible
But I don't know why WPF throws Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead for your original XAML instead of some more meaningful error.

ASP.NET MVC 2 Membership users table mdf file

I have an MVC 2 project where I have my own *.mdf file in the App_Data directory. The *.mdf file contains my normal tables but not a users table.
Is it possible to add a Users table to my *.mdf file and work with that instead of the simple register form? (if so: how could this be done?)
Because I don't know how to do these things above, I searched and only found steps to add build in Membership to my mdf file and I tried it:
I tried to add normal build in Membership to my *.mdf file with this:
aspnet_regsql.exe -C CONSTRINGHERE -d PATHTOMDFFILEHERE -A all
and I changed my Web.config file to this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="CompanyDBEntities" connectionString="metadata=res://*/Models.CompanyDB.csdl|res://*/Models.CompanyDB.ssdl|res://*/Models.CompanyDB.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\CompanyData.mdf;Integrated Security=True;User Instance=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<membership defaultProvider="CompanyDBSqlProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add name="CompanyDBSqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="CompanyDBEntities"
applicationName="/"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
/>
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider"
connectionStringName="CompanyDBEntities" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider"
connectionStringName="CompanyDBEntities" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
<pages>
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
I did not modify anything else. I did not change the AccountController or something.
I builded and ran my MVC 2 application and went to LogOn and registered an account but got stuck there:
Account creation was unsuccessful. Please correct the errors and try again.
* The password retrieval answer provided is invalid. Please check the value and try again.
Summary:
I thought that it would be better to have a Users table in my *.mdf file but I don't know how to do the register/login/logout/membership/etc... things with an own users table.
So I tried adding Membership to my own *.mdf file so that everything would be in that one *.mdf file but that gives me also problems.
Maybe this info is important:
In the future I want it to be possible to let users register and login via Hotmail, Gmail, OpenId and I should need more fields like website, nickname, avatar, etc... other than the basic register form now. Also would need to show a profilepage from the user on the website.
Could anybody help me out?
PS: I don't have experience with Membership in ASP.NET :s
I encountered the same problem. You can customize the user register table by doing these:
First of all, configure the sqlmemberprovider service in web.config:
' add connectionStringName="PhotoSocialMemberService" applicationName="PhotoSocial"
minRequiredPasswordLength="5" minRequiredNonalphanumericCharacters="0"
requiresQuestionAndAnswer="true"
name="PhotoSocailMember" type="System.Web.Security.SqlMembershipProvider" /'
Edit the AccountModel.cs., look for
the method "CreateUser", the
abstract class should be like this:
public abstract class MembershipProvider : ProviderBase
{...
public abstract MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
}
in the AccountModel.cs you can find implementation of the abstract method in
public interface IMembershipService
{
int MinPasswordLength { get; }
bool ValidateUser(string userName, string password);
MembershipCreateStatus CreateUser(string userName, string password, string email, string passwordquestion, string passwordanswer);
bool ChangePassword(string userName, string oldPassword, string newPassword);
}
and in
public MembershipCreateStatus CreateUser(string userName, string password, string email, string passwordquestion, string passwordanswer)
{
if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
MembershipCreateStatus status;
_provider.CreateUser(userName, password, email, passwordquestion, passwordanswer, true, null, out status);
return status;
}
add as many as parameters as you like.
Edit the register model in RegisterModel in AccountModel.cs, add string you want to put into the registerModel:
public class RegisterModel
{[Required]
[DisplayName("User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[DisplayName("Email address")]
public string Email { get; set; }
[Required]
[ValidatePasswordLength]
[DataType(DataType.Password)]
[DisplayName("Password")]
public string Password { get; set; }
[Required]
[DataType(DataType.Password)]
[DisplayName("Confirm password")]
public string ConfirmPassword { get; set; }
[Required]
[DisplayName("Password security question")]
public string PasswordQuestion { get; set; }
[Required]
[DataType(DataType.Password)]
[DisplayName("Password security answer")]
public string PasswordAnswer { get; set; }
}
Last, rewrite the Register.aspx page, add the html tag:
Html.LabelFor(m => m.PasswordQuestion)
Most important, you need to change the _provider from readonly to private
public class AccountMembershipService : IMembershipService
{
private MembershipProvider _provider;
}
You can add your validation methods through this progress.

EF4 POCO (not using T4): Mapping and metadata information could not be found for EntityType

I have a pretty simple console project with an entity model (containing two simple entities), two handmade POCOs and a handmade Context class. The program fires a simple query against the DB and everything including LazyLoading works fine.
The problem: As soon as i add another Entity data model (even if i add an empty one), the calls to CreateObjectSet in Ef2PlaygroundModel_3Container throw the following exception:
Unhandled Exception: System.InvalidOperationException: Mapping and metadata information could not be found for EntityType 'EF2_Playground.Driver'.
at System.Data.Objects.ObjectContext.GetTypeUsage(Type entityCLRType)
at System.Data.Objects.ObjectContext.GetEntitySetFromContainer(EntityContainer container, Type entityCLRType, String exceptionParameterName)
at System.Data.Objects.ObjectContext.GetEntitySetForType(Type entityCLRType, String exceptionParameterName)
at System.Data.Objects.ObjectContext.CreateObjectSet[TEntity]()
at EF2_Playground.Ef2PlaygroundModel_3Container.get_Drivers() in C:\...\Ef2PlaygroundModel_3Pocos.cs:line 64
at EF2_Playground.Program.Main(String[] args) in C:\...\Program.cs:line 15
Does anyone have an idea about what is going wrong here?
That is the working project:
Ef2PlaygroundModel_3.edmx:
Code Generation Strategy is set to "None"
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="Ef2PlaygroundModel_3.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="Ef2PlaygroundModel_3StoreContainer">
<EntitySet Name="Cars" EntityType="Ef2PlaygroundModel_3.Store.Cars" store:Type="Tables" Schema="dbo"/>
<EntitySet Name="Drivers" EntityType="Ef2PlaygroundModel_3.Store.Drivers" store:Type="Tables" Schema="dbo"/>
<EntitySet Name="CarDriver" EntityType="Ef2PlaygroundModel_3.Store.CarDriver" store:Type="Tables" Schema="dbo"/>
<AssociationSet Name="FK_CarDriver_Car" Association="Ef2PlaygroundModel_3.Store.FK_CarDriver_Car">
<End Role="Car" EntitySet="Cars"/>
<End Role="CarDriver" EntitySet="CarDriver"/>
</AssociationSet>
<AssociationSet Name="FK_CarDriver_Driver" Association="Ef2PlaygroundModel_3.Store.FK_CarDriver_Driver">
<End Role="Driver" EntitySet="Drivers"/>
<End Role="CarDriver" EntitySet="CarDriver"/>
</AssociationSet>
</EntityContainer>
<EntityType Name="Cars">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false"/>
<Property Name="Brand" Type="nvarchar(max)" Nullable="false"/>
<Property Name="Model" Type="nvarchar(max)" Nullable="false"/>
<Property Name="ReleaseDate" Type="datetime" Nullable="true"/>
</EntityType>
<EntityType Name="Drivers">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false"/>
<Property Name="Name" Type="nvarchar(max)" Nullable="false"/>
</EntityType>
<EntityType Name="CarDriver">
<Key>
<PropertyRef Name="Cars_Id"/>
<PropertyRef Name="Drivers_Id"/>
</Key>
<Property Name="Cars_Id" Type="int" Nullable="false"/>
<Property Name="Drivers_Id" Type="int" Nullable="false"/>
</EntityType>
<Association Name="FK_CarDriver_Car">
<End Role="Car" Type="Ef2PlaygroundModel_3.Store.Cars" Multiplicity="1"/>
<End Role="CarDriver" Type="Ef2PlaygroundModel_3.Store.CarDriver" Multiplicity="*"/>
<ReferentialConstraint>
<Principal Role="Car">
<PropertyRef Name="Id"/>
</Principal>
<Dependent Role="CarDriver">
<PropertyRef Name="Cars_Id"/>
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_CarDriver_Driver">
<End Role="CarDriver" Type="Ef2PlaygroundModel_3.Store.CarDriver" Multiplicity="*"/>
<End Role="Driver" Type="Ef2PlaygroundModel_3.Store.Drivers" Multiplicity="1"/>
<ReferentialConstraint>
<Principal Role="Driver">
<PropertyRef Name="Id"/>
</Principal>
<Dependent Role="CarDriver">
<PropertyRef Name="Drivers_Id"/>
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="Ef2PlaygroundModel_3" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
<EntityContainer Name="Ef2PlaygroundModel_3Container" annotation:LazyLoadingEnabled="true">
<EntitySet Name="Cars" EntityType="Ef2PlaygroundModel_3.Car"/>
<EntitySet Name="Drivers" EntityType="Ef2PlaygroundModel_3.Driver"/>
<AssociationSet Name="CarDriver" Association="Ef2PlaygroundModel_3.CarDriver">
<End Role="Car" EntitySet="Cars"/>
<End Role="Driver" EntitySet="Drivers"/>
</AssociationSet>
</EntityContainer>
<EntityType Name="Car">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity"/>
<Property Type="String" Name="Brand" Nullable="false"/>
<Property Type="String" Name="Model" Nullable="false"/>
<Property Type="DateTime" Name="ReleaseDate" Nullable="true"/>
<NavigationProperty Name="Drivers" Relationship="Ef2PlaygroundModel_3.CarDriver" FromRole="Car" ToRole="Driver"/>
</EntityType>
<EntityType Name="Driver">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity"/>
<Property Type="String" Name="Name" Nullable="false"/>
<NavigationProperty Name="Cars" Relationship="Ef2PlaygroundModel_3.CarDriver" FromRole="Driver" ToRole="Car"/>
</EntityType>
<Association Name="CarDriver">
<End Type="Ef2PlaygroundModel_3.Car" Role="Car" Multiplicity="*"/>
<End Type="Ef2PlaygroundModel_3.Driver" Role="Driver" Multiplicity="*"/>
</Association>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
<EntityContainerMapping StorageEntityContainer="Ef2PlaygroundModel_3StoreContainer" CdmEntityContainer="Ef2PlaygroundModel_3Container">
<EntitySetMapping Name="Cars">
<EntityTypeMapping TypeName="IsTypeOf(Ef2PlaygroundModel_3.Car)">
<MappingFragment StoreEntitySet="Cars">
<ScalarProperty Name="Id" ColumnName="Id"/>
<ScalarProperty Name="Brand" ColumnName="Brand"/>
<ScalarProperty Name="Model" ColumnName="Model"/>
<ScalarProperty Name="ReleaseDate" ColumnName="ReleaseDate"/>
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="Drivers">
<EntityTypeMapping TypeName="IsTypeOf(Ef2PlaygroundModel_3.Driver)">
<MappingFragment StoreEntitySet="Drivers">
<ScalarProperty Name="Id" ColumnName="Id"/>
<ScalarProperty Name="Name" ColumnName="Name"/>
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="CarDriver" TypeName="Ef2PlaygroundModel_3.CarDriver" StoreEntitySet="CarDriver">
<EndProperty Name="Car">
<ScalarProperty Name="Id" ColumnName="Cars_Id"/>
</EndProperty>
<EndProperty Name="Driver">
<ScalarProperty Name="Id" ColumnName="Drivers_Id"/>
</EndProperty>
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<edmx:Designer xmlns="http://schemas.microsoft.com/ado/2008/10/edmx">
<edmx:Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly"/>
</DesignerInfoPropertySet>
</edmx:Connection>
<edmx:Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true"/>
<DesignerProperty Name="EnablePluralization" Value="False"/>
<DesignerProperty Name="CodeGenerationStrategy" Value="None"/>
</DesignerInfoPropertySet>
</edmx:Options>
<!-- Diagram content (shape and connector positions) -->
<edmx:Diagrams>
<Diagram Name="Ef2PlaygroundModel_3">
<EntityTypeShape EntityType="Ef2PlaygroundModel_3.Car" Width="1.5" PointX="3.25" PointY="1.625" Height="1.787985026041667"/>
<EntityTypeShape EntityType="Ef2PlaygroundModel_3.Driver" Width="1.5" PointX="5.375" PointY="1.625" Height="1.59568359375"/>
<AssociationConnector Association="Ef2PlaygroundModel_3.CarDriver">
<ConnectorPoint PointX="4.75" PointY="2.422841796875"/>
<ConnectorPoint PointX="5.375" PointY="2.422841796875"/>
</AssociationConnector>
</Diagram>
</edmx:Diagrams>
</edmx:Designer>
</edmx:Edmx>
app.config:
<configuration>
<connectionStrings>
<add
name="Ef2PlaygroundModel_3Container"
connectionString="metadata=res://*/Ef2PlaygroundModel_3.csdl|res://*/Ef2PlaygroundModel_3.ssdl|res://*/Ef2PlaygroundModel_3.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\SqlExpress;Initial Catalog=Ef2PlaygroundModel_3;Integrated Security=True;MultipleActiveResultSets=True""
providerName="System.Data.EntityClient"
/>
</connectionStrings>
</configuration>
Ef2PlaygroundModel_3Pocos.cs:
using System;
using System.Collections.Generic;
using System.Data.Objects;
namespace EF2_Playground
{
public class Car
{
public Car()
{
Drivers = new List<Driver>();
}
public int Id { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public DateTime? ReleaseDate { get; set; }
public virtual List<Driver> Drivers { get; private set; }
}
public class Driver
{
public Driver()
{
Cars = new List<Car>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Car> Cars { get; private set; }
}
public class Ef2PlaygroundModel_3Container : ObjectContext
{
public Ef2PlaygroundModel_3Container()
: base("name=Ef2PlaygroundModel_3Container")
{
ContextOptions.LazyLoadingEnabled = true;
}
public IObjectSet<Car> Cars
{
get { return CreateObjectSet<Car>(); }
}
public IObjectSet<Driver> Drivers
{
get { return CreateObjectSet<Driver>(); }
}
}
}
Program.cs:
using System;
namespace EF2_Playground
{
class Program
{
static void Main(string[] args)
{
using (var ctx = new Ef2PlaygroundModel_3Container())
{
foreach (var driver in ctx.Drivers)
{
Console.WriteLine(driver.Name);
foreach (var car in driver.Cars)
{
Console.WriteLine(" drives a {0} - {1} (released on {2})", car.Brand, car.Model, car.ReleaseDate);
}
}
}
}
}
}
And finally Model1.edmx that breaks the whole thing as soon as i add it to the project:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" Namespace="Model1.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005">
<EntityContainer Name="Model1TargetContainer">
</EntityContainer>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="Model1" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
<EntityContainer Name="Model1Container" annotation:LazyLoadingEnabled="true">
</EntityContainer>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs" Space="C-S">
<Alias Key="Model" Value="Model1"/>
<Alias Key="Target" Value="Model1.Store"/>
<EntityContainerMapping CdmEntityContainer="Model1Container" StorageEntityContainer="Model1TargetContainer">
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<edmx:Designer xmlns="http://schemas.microsoft.com/ado/2008/10/edmx">
<edmx:Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly"/>
</DesignerInfoPropertySet>
</edmx:Connection>
<edmx:Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true"/>
<DesignerProperty Name="EnablePluralization" Value="False"/>
</DesignerInfoPropertySet>
</edmx:Options>
<!-- Diagram content (shape and connector positions) -->
<edmx:Diagrams>
<Diagram Name="Model1"/>
</edmx:Diagrams>
</edmx:Designer>
</edmx:Edmx>
Ok, i guess i've got it. I reduced the second model (the one that brakes the project) to the following:
Class1.cs
using System.Data.Objects.DataClasses;
[assembly: EdmSchemaAttribute()]
Bang! The well known exception appears.
As in so many cases, reading the documentation helps:
Mapping POCO entities is not supported if any mapping attributes are applied to custom data classes, including EdmSchemaAttribute at the assembly level.
Sure, i do not literally add mapping attributes to CUSTOM data classes but that doesn't matter for the EdmSchemaAttribute since that one lives on the assembly level.
Adding the second non-POCO model causes code generation resulting in a class that contains (at least) the EdmSchemaAttribute and that is not supported.
What i've learned: Don't mix POCO and non-POCO models in one assembly.
My guess is that ef is lookig at the wrong model. Is there any chance that the models are using the same namespace? You can modify the CSDLs namespace in the property window. What happens if you modify the csdl namespace of the new, empty model?
In the properties of your *.edmx if you are using POCO, then you should set the CodeGenerationStrategy to none.