Value cannot be null when using join in OrmLite / Servicestack / Linqpad - linqpad

When joining two tables I get
ArgumentNullException: Value cannot be null. Parameter name: key.
This happens after executing the query, change any line in Linqpad and execute again.
using (var db = _factory.OpenDbConnection())
{
var q = db.From<Customer>()
.Join<Customer, Address>();
var results = db.SelectMulti<Customer, Address>(q);
results.Dump();
}
Customer
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
Address
public class Address
{
public int Id { get; set; }
public int CustomerId { get; set; }
}
ServiceStack throws this error
at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
at ServiceStack.TypeExtensions.GetActivator(ConstructorInfo ctor)
at ServiceStack.OrmLite.OrmLiteUtils.ConvertToList[T](IDataReader reader, IOrmLiteDialectProvider dialectProvider, HashSet`1 onlyFields)
at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ExprConvertToList[T](IDbCommand dbCmd, String sql, IEnumerable`1 sqlParams, HashSet`1 onlyFields)
at ServiceStack.OrmLite.ReadExpressionCommandExtensions.SelectMulti[T,T2](IDbCommand dbCmd, SqlExpression`1 q)
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func`2 filter)
at UserQuery.Main() in C:\Users\kairu\AppData\Local\Temp\LINQPad5\_uimlqbjb\plnhhb\LINQPadQuery.cs:line 54
at LINQPad.ExecutionModel.ClrQueryRunner.Run()
at LINQPad.ExecutionModel.Server.RunQuery(QueryRunner runner)
at LINQPad.ExecutionModel.Server.StartQuery(QueryRunner runner)
at LINQPad.ExecutionModel.Server.<>c__DisplayClass153_0.<ExecuteClrQuery>b__0()
at LINQPad.ExecutionModel.Server.SingleThreadExecuter.Work()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Using ServiceStack version 5.1.0 net45

This example works as expected on Gistlyn:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Address
{
public int Id { get; set; }
public int CustomerId { get; set; }
}
db.CreateTable<Customer>();
db.CreateTable<Address>();
db.Insert(new Customer { Id = 1, Name = "C" });
db.Insert(new Address { Id = 1, CustomerId = 1 });
var q = db.From<Customer>()
.Join<Customer,Address>();
var results = db.SelectMulti<Customer, Address>(q);
results.PrintDump();
It might be an issue with LINQ Pad.

Related

Why is Cosmos DB giving me an "The input name '{' is invalid" error when I call CreateItemAsync

I am working on an ASP.Net Core 3.0 API with an Azure Cosmos DB as the persistence store. This is my first attempt at working with Cosmos DB. When I try to create a new item (document), I am getting back an error in Postman that says...
"Response status code does not indicate success: 400 Substatus: 0
Reason: (Message: {\"Errors\":[\"The input name '{' is invalid.
Ensure to provide a unique non-empty string less than '1024' characters."
I cannot figure out what is causing this problem.
I am using the Microsoft.Azure.Cosmos v3.4.0 nuget in my project
Here is the method in my repository for adding the new Account document.
public async Task AddAccountAsync(Account account)
{
await _container.CreateItemAsync(account, new PartitionKey(account.Id));
}
Here is a pic of the property values when I hover over the "Account account" object while in debug mode.
My container in Cosmos DB is set up with /id as the partition key.
Here is my request body in Postman;
{
"id": "00000000-0000-0000-0000-000000000000",
"accountName": "Test Company 1",
"accountType": 1,
"ownerId": "00000000-0000-0000-0000-000000000000",
"isTaxExempt": false,
"mailJobProxyId": "00000000-0000-0000-0000-000000000000",
"salesPersonId": "00000000-0000-0000-0000-000000000000"
}
Here is the Account class;
public class Account
{
// Aggregate state properties
[JsonProperty(PropertyName = "id")]
public AccountId Id { get; set; }
[JsonProperty(PropertyName = "accountName")]
public AccountName AccountName { get; set; }
[JsonProperty(PropertyName = "accountType")]
public AccountTypes AccountType { get; set; }
[JsonProperty(PropertyName = "ownerId")]
public OwnerId OwnerId { get; set; }
[JsonProperty(PropertyName = "isTaxExempt")]
public bool IsTaxExempt { get; set; }
[JsonProperty(PropertyName = "mailJobProxyId")]
public MailJobProxyId MailJobProxyId { get; set; }
[JsonProperty(PropertyName = "salesPersonId")]
public SalesPersonId SalesPersonId { get; set; }
[JsonProperty(PropertyName = "addresses")]
public List<Address.Address> Addresses { get; set; }
[JsonProperty(PropertyName = "contacts")]
public List<Contact.Contact> Contacts { get; set; }
[JsonProperty(PropertyName = "postagePaymentMethods")]
public List<PostagePaymentMethod.PostagePaymentMethod> PostagePaymentMethods { get; set; }
public Account(string id, string accountName, AccountTypes accountType, string ownerId, Guid mailJobProxyId, Guid salesPersonId, bool isTaxExempt)
{
Id = AccountId.FromString(id);
AccountName = AccountName.FromString(accountName);
AccountType = accountType;
OwnerId = OwnerId.FromString(ownerId);
MailJobProxyId = new MailJobProxyId(mailJobProxyId);
SalesPersonId = new SalesPersonId(salesPersonId);
IsTaxExempt = isTaxExempt;
Addresses = new List<Address.Address>();
Contacts = new List<Contact.Contact>();
PostagePaymentMethods = new List<PostagePaymentMethod.PostagePaymentMethod>();
Status = Status.Active;
}
}
Please let me know if you need other code examples.
UPDATE 11/6/19 at 6:43p EST
Here is the AccountId value object
public class AccountId : Value<AccountId>
{
public string Value { get; internal set; }
// Parameterless constructor for serialization requirements
protected AccountId() { }
internal AccountId(string value) => Value = value;
// Factory pattern
public static AccountId FromString(string accountId)
{
CheckValidity(accountId);
return new AccountId(accountId);
}
public static implicit operator string(AccountId accountId) => accountId.Value;
private static void CheckValidity(string value)
{
if (!Guid.TryParse(value, out _))
{
throw new ArgumentException(nameof(value), "Account Id is not a GUID.");
}
}
}
And here is the initialization class in Startup.cs that sets up the database and container.
private static async Task<AccountsRepository> InitializeCosmosClientAccountInstanceAsync(IConfigurationSection configurationSection)
{
var databaseName = configurationSection.GetSection("DatabaseName").Value;
string uri = configurationSection.GetSection("Uri").Value;
string key = configurationSection.GetSection("Key").Value;
CosmosClientBuilder clientBuilder = new CosmosClientBuilder(uri, key);
CosmosClient client = clientBuilder
.WithConnectionModeDirect()
.Build();
DatabaseResponse database = await client.CreateDatabaseIfNotExistsAsync(databaseName);
string containerName = configurationSection.GetSection("AccountsContainerName").Value;
await database.Database.CreateContainerIfNotExistsAsync(containerName, "/id");
AccountsRepository cosmosDbService = new AccountsRepository(client, databaseName, containerName);
return cosmosDbService;
}
Here is the stack trace from when the error occurs;
stackTrace": " at Microsoft.Azure.Cosmos.ResponseMessage.EnsureSuccessStatusCode()\r\n
at Microsoft.Azure.Cosmos.CosmosResponseFactory.ToObjectInternal[T]
(ResponseMessage cosmosResponseMessage, CosmosSerializer jsonSerializer)\r\n
at Microsoft.Azure.Cosmos.CosmosResponseFactory.
<CreateItemResponseAsync>b__6_0[T](ResponseMessage cosmosResponseMessage)\r\n
at Microsoft.Azure.Cosmos.CosmosResponseFactory.ProcessMessageAsync[T]
(Task`1 cosmosResponseTask, Func`2 createResponse)\r\n at
Delivery.Api.Infrastructure.AccountsRepository.AddAccountAsync(Account
account) in
C:\\AzureDevOps\\Delivery\\Delivery.Api\\Accounts\\AccountsRepository.cs:line 20\r\n
at Delivery.Api.Accounts.AccountsApplicationService.HandleCreate(Create cmd)
in C:\\AzureDevOps\\Delivery\\Delivery.Api\\Accounts\\AccountsApplicationService.cs:line 43\r\n
at Delivery.Api.Infrastructure.RequestHandler.HandleCommand[T](T request, Func`2 handler, ILogger log)
in C:\\AzureDevOps\\Delivery\\Delivery.Api\\Infrastructure\\RequestHandler.cs:line 16
You may need to create your custom converter for your AccountId, OwnerId and so on.
Here is my test:
class AccountIdConverter
class AccountIdConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(AccountId));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return AccountId.FromString(JToken.Load(reader).ToString());
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken.FromObject(value.ToString()).WriteTo(writer);
}
}
class AccountId
Add toString method, and set to use custom converter
[JsonConverter(typeof(AccountIdConverter))]
public class AccountId
{
public string Value { get; internal set; }
protected AccountId() { }
internal AccountId(string value) => Value = value;
public static AccountId FromString(string accountId)
{
CheckValidity(accountId);
return new AccountId(accountId);
}
public static implicit operator string(AccountId accountId) => accountId.Value;
public override string ToString()
{
return Value;
}
private static void CheckValidity(string value)
{
if (!Guid.TryParse(value, out _))
{
throw new ArgumentException(nameof(value), "Account Id is not a GUID.");
}
}
}
class Account
class Account
{
[JsonProperty(PropertyName = "id")]
public AccountId Id { get; set; }
public Account(string id)
{
Id = AccountId.FromString(id);
}
}
Test
static void Main(string[] args)
{
// Test toString
AccountId accountId = AccountId.FromString(Guid.NewGuid().ToString());
Console.WriteLine(accountId.ToString());
// Test AccountIdConverter
Console.WriteLine(JsonConvert.SerializeObject(accountId));
// Test for serializing Account
Account account = new Account(Guid.NewGuid().ToString());
string accountJson = JsonConvert.SerializeObject(account);
Console.WriteLine(accountJson);
// Test for deserializing Account
Account accountDeserialized = JsonConvert.DeserializeObject<Account>(accountJson);
Console.WriteLine(accountDeserialized.Id);
Console.ReadLine();
}
Result
You can see that the Account object which contains an AccountId object can be serialized and deserialized correctly as expected.

Executing an SP in EF Core

I'm trying to execute an sp in ef core.
ALTER PROCEDURE [dbo].[usp_get_counts_for_event_type_for_single_date]
#OrgCode varchar(5),
#ProcessDate date
AS
BEGIN
SET NOCOUNT ON
DECLARE #StartTime time = '00:00:00'
DECLARE #EndTime time = '23:59:59'
DECLARE #PeriodStart datetime = CONVERT(datetime, #ProcessDate) + CONVERT(datetime, #StartTime)
DECLARE #PeriodEnd datetime = CONVERT(datetime, #ProcessDate) + CONVERT(datetime, #EndTime)
-- Insert statements for procedure here
SELECT CONVERT(VARCHAR(100), et.DisplayName) as Title,
et.DashboardColour as Colour,
count(et.EventTypeId) as Count
from EventType et
join EventLog el on et.EventTypeId = el.EventTypeId
WHERE el.StartTime BETWEEN #PeriodStart AND #PeriodEnd
group by et.DisplayName, et.DashboardColour
END
I have defined a data model class for the sp results.
public class GroupedCountResult
{
[Key]
[Column("varchar(100)")]
public string Title { get; set; }
[Column("varchar(20)")]
public string Colour { get; set; }
[Required]
public int Count { get; set; }
}
And then in DbContext.cs It's been added as a DbSet in the context
public DbSet<GroupedCountResult> GroupedCountResults { get; set; }
Then I try to execute it in an Core 2.2 MVC Controller. This is my weak point. I'm trying to chop the results up into strings that are then used in javascript for a pie chart. Hardcoded values until I get this working.
public async Task<ActionResult> Index()
{
StringBuilder sbLabels = new StringBuilder();
StringBuilder sbColours = new StringBuilder();
StringBuilder sbCounts = new StringBuilder();
string OrgCode = "HVO";
DateTime ProcessDate = new DateTime(2019, 08, 01); //.ToString("yyyyMMdd");
IEnumerable<GroupedCountResult> results = await _context.GroupedCountResults
.FromSql($"usp_get_counts_for_event_type_for_single_date #p0, #p1", OrgCode, ProcessDate)
.ToListAsync();
foreach(GroupedCountResult result in results) <--exception here
{
sbLabels.AppendFormat("'{0}',", result.Title);
sbColours.AppendFormat("'{0}',", result.Colour);
sbCounts.AppendFormat("{0},", result.Count);
}
ViewBag.Labels = sbLabels.ToString().TrimEnd(',');
ViewBag.Colours = sbColours.ToString().TrimEnd(',');
ViewBag.Counts = sbCounts.ToString().TrimEnd(',');
return View();
}
From the logs. I preferred the string interpolation version, but this seems closer to working.
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (31ms) [Parameters=[#p0='?' (Size = 4000), #p1='?' (DbType = DateTime2)], CommandType='Text', CommandTimeout='30']
usp_get_counts_for_event_type_for_single_date #p0, #p1
I've worked through a few exceptions. It's now throwing an exception after the execution, implying there's something wrong with the results.
Microsoft.EntityFrameworkCore.Query:Error: An exception occurred while iterating over the results of a query for context type 'Ctrack.Dashboard.Data.DbContext'.
System.InvalidOperationException: The required column 'varchar(100)' was not present in the results of a 'FromSql' operation.
at Microsoft.EntityFrameworkCore.Query.Sql.Internal.FromSqlNonComposedQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.<NotifyReaderCreated>b__14_0(FactoryAndReader s)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:line 106
at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 98
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
System.InvalidOperationException: The required column 'varchar(100)' was not present in the results of a 'FromSql' operation.
at Microsoft.EntityFrameworkCore.Query.Sql.Internal.FromSqlNonComposedQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.<NotifyReaderCreated>b__14_0(FactoryAndReader s)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.MoveNextCore(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:line 106
at System.Linq.AsyncEnumerable.AsyncIterator`1.MoveNext(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 98
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Ctrack.Dashboard.Controllers.HomeController.Index (Ctrack.Dashboard) in 1375.9283ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Ctrack.Dashboard.Controllers.HomeController.Index (Ctrack.Dashboard)'
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware:Error: An unhandled exception has occurred while executing the request.
Has it lost track of the column name? I've tried converting the column to varchar(100). All the info on executing sp's implied it would be easier than this.
The problem lies in your model Data Annotation.If you would like to specify an exact data type for a column, you need to use [Column(TypeName = "varchar(100)")] instead of [Column("varchar(200)")] which will map the column name not column type
public class GroupedCountResult
{
[Key]
[Column(TypeName ="varchar(100)")]
public int Title { get; set; }
[Column(TypeName = "varchar(20)")]
public string Colour { get; set; }
}
Refer to
https://learn.microsoft.com/en-us/ef/core/modeling/relational/data-types
https://learn.microsoft.com/en-us/ef/core/modeling/relational/columns
Here is how i am calling my stored procedure in .net core
public class DbUtilities
{
private readonly ILogHandler _oisLogger;
private readonly SB1_VVFContext _context;
public DbUtilities(ILogHandler oislogger, SB1_VVFContext context)
{
_oisLogger = oislogger;
_context = context;
}
public IEnumerable<VehicleSearchResultDTO> SearchVehicleRecords(VehicleSearchCriteriaDTO Criteria)
{
List<VehicleSearchResultDTO> result = new List<VehicleSearchResultDTO>();
VehicleSearchResultDTO vehRec = null;
try
{
//Define Command Object
_context.Database.OpenConnection();
DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();
SqlParameter refnum = new SqlParameter("#RefNum", SqlDbType.VarChar, 10)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.RefNum)) ? Criteria.RefNum : string.Empty
};
//Define Input parameters
SqlParameter vin = new SqlParameter("#Vin", SqlDbType.VarChar, 100)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.Vin)) ? Criteria.Vin : string.Empty
};
SqlParameter owner = new SqlParameter("#Owner", SqlDbType.VarChar, 200)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.RegisteredOwner)) ? Criteria.RegisteredOwner : string.Empty
};
SqlParameter plate = new SqlParameter("#Plate", SqlDbType.VarChar, 10)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.Plate)) ? Criteria.Plate : string.Empty
};
SqlParameter email = new SqlParameter("#Email", SqlDbType.VarChar, 200)
{
Direction = ParameterDirection.Input,
Value = (!string.IsNullOrWhiteSpace(Criteria.Email)) ? Criteria.Email : string.Empty
};
SqlParameter VehicleReviewStatusId = new SqlParameter("#VehicleReviewStatusId", SqlDbType.Int)
{
Direction = ParameterDirection.Input,
Value = Criteria.VehicleReviewStatusId
};
//Define properties for command object and execute the SP
cmd.CommandText = "usp_Vehicle_Search_Result";
cmd.Parameters.Add(refnum);
cmd.Parameters.Add(vin);
cmd.Parameters.Add(owner);
cmd.Parameters.Add(plate);
cmd.Parameters.Add(email);
cmd.Parameters.Add(VehicleReviewStatusId);
cmd.CommandTimeout = 10;
cmd.CommandType = CommandType.StoredProcedure;
DbDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
//Get Search Result
while (reader.Read())
{
vehRec = new VehicleSearchResultDTO
{
VehicleID = (Guid)reader["VehicleId"],
ReferenceNumber = reader["ReferenceNumber"].ToString(),
SubmitterEmail = reader["EmailAddress"].ToString(),
Status = reader["StatusName"].ToString(),
SubmittedDate = CheckNull<DateTime?>(reader["DateSubmitted"]),
VIN = reader["VIN"].ToString(),
Year = CheckNull<int>(reader["Year"]),
Make = reader["Make"].ToString(),
LicensePlate = reader["LicensePlate"].ToString(),
ROName = reader["ROName"].ToString(),
StatusColor = reader["StatusColor"].ToString()
};
result.Add(vehRec);
}
}
else
{
result = null;
}
}
catch (Exception ex)
{
_oisLogger.LogError(2205, $"ERROR SearchVehicleRecords", ex);
}
finally
{
_context.Database.CloseConnection();
}
return result;
}
Here is the input object:
public class VehicleSearchCriteriaDTO
{
public VehicleSearchCriteriaDTO()
{
}
[Display(Name = "Ref#")]
public string RefNum { get; set; }
[Display(Name = "VIN")]
public string Vin { get; set; }
[Display(Name = "Reg Owner")]
public string RegisteredOwner { get; set; }
[Display(Name = "Plate")]
public string Plate { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
public int VehicleReviewStatusId { get; set; }
}
Here is the output object:
public class VehicleSearchResultDTO
{
[Display(Name = "Owner")]
public string ROName { get; set; }
[Display(Name = "RefNum")]
public string ReferenceNumber { get; set; }
[Display(Name = "VIN")]
public string VIN { get; set; }
[Display(Name = "Plate")]
public string LicensePlate { get; set; }
[Display(Name = "Year")]
public int Year { get; set; }
[Display(Name = "Make")]
public string Make { get; set; }
[Display(Name = "Submitter Email")]
public string SubmitterEmail { get; set; }
[Display(Name = "Submitted Date")]
public DateTime? SubmittedDate { get; set; }
[Display(Name = "Status")]
public string Status { get; set; }
public Guid VehicleID { get; set; }
public string StatusColor { get; set; }
}
I did not add these classes to the dbcontext or the proc to the dbcontext. Also, i would suggest you comment your code out to only fetch one result variable at a time.
See if the mapping to the object from the SP call works well, then add another variable/parameter.

How to use NHibernate DiscriminateSubClassesOnColumn and References for the same column

The Setup
I am using FluentNHibernate 1.4.0 for my NHibernate 3.3.3-SP1 mappings in a .NET4.0 library. I'm using the "table-per-inheritance" approach for my type hierarchy as follows:
-- Different process types potentially use
-- different types of reference values
CREATE TABLE ProcessTypes
(Id INT PRIMARY KEY)
-- Contains reference values for value comparisons
CREATE TABLE ProcessReferenceValues
(Id INT PRIMARY KEY IDENTITY(1,1),
ProcessTypeId INT FOREIGN KEY REFERENCES ProcessTypes(Id),
FloatReferencesValue FLOAT NULL,
IntReferenceValue INT NULL)
// POCOs
class ProcessReferenceValues
{
public virtual int Id { get; set; }
public virtual ProcessTypes ProcessType { get; set; }
public virtual float? FloatReferenceValue { get; set; }
public virtual int? IntReferenceValue { get; set; }
}
class IntProcessReferenceValues : ProcessReferenceValues { }
class FloatProcessReferenceValues : ProcessReferenceValues { }
enum ProcessTypeName : int
{
IntProcess = 1,
FloatProcess = 2
}
class ProcessTypes
{
public virtual int Id { get; set; }
public virtual ProcessTypeName Name { get; set; }
}
// FluentNHibernate Mappings
class ProcessReferenceValuesMap
: FluentNHibernate.Mapping.ClassMap<ProcessReferenceValues>
{
public ProcessReferenceValuesMap()
{
string processTypeId = "ProcessTypeId";
this.Id(x => x.Id);
this.Map(x => x.FloatReferenceValue).Nullable();
this.Map(x => x.IntReferenceValue).Nullable();
// Here is the tricky bit
this.References(x => x.ProcessType, processTypeId);
this.DiscriminateSubClassesOnColumn(processTypeId);
}
}
class IntProcessReferenceValuesMap
: FluentNHibernate.Mapping.SubclassMap<IntProcessReferenceValues>
{
public IntProcessReferenceValuesMap()
{
this.DiscriminatorValue((int)ProcessTypeName.IntProcess);
}
}
class FloatProcessReferenceValuesMap
: FluentNHibernate.Mapping.SubclassMap<FloatProcessReferenceValues>
{
public FloatProcessReferenceValuesMap()
{
this.DiscriminatorValue((int)ProcessTypeName.FloatProcess);
}
}
class ProcessPeriodTypesMap : FluentNHibernate.Mapping.ClassMap<ProcessPeriodTypes>
{
public ProcessPeriodTypesMap()
{
this.ReadOnly();
this.Id(x => x.Id, "id");
this.Map(x => x.Name, "id").ReadOnly().CustomType<PeriodTypeName>();
}
}
The Problem
While reading from the database works like a charm - the appropriate sub classes are selected correctly - saving a new process reference value gives me an exception:
// Reading
var processType =
(from type in session.Query<ProcessTypes>()
where type.Name == ProcessTypeName.IntProcess
select type).FirstOrDefault(); // OK, finds the IntProcess
var referenceValues =
(from val in session.Query<ProcessReferenceValues>()
select val).ToList(); // OK, finds the appropriate subclasses
// Inserting
var processType = new ProcessTypes
{
Id = (int)ProcessTypeName.IntProcess
};
var referenceValue = new ProcessReferenceValues
{
FloatReferenceValue = 0.7f,
IntReferenceValue = null,
ProcessType = processType // Needs the appropriate ProcessType
};
session.Save(referenceValue); // <- BOOM!
Error dehydrating property value for ProcessReferenceValues.ProcessType
Invalid Index 2 for OleDbParameterCollection with Count=2.
bei System.Data.OleDb.OleDbParameterCollection.RangeCheck(Int32 index)
bei System.Data.OleDb.OleDbParameterCollection.GetParameter(Int32 index)
bei System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item(Int32 index)
bei NHibernate.Type.Int32Type.Set(IDbCommand rs, Object value, Int32 index) in p:\nhibernate-core\src\NHibernate\Type\Int32Type.cs:Zeile 60.
bei NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd, Object value, Int32 index) in p:\nhibernate-core\src\NHibernate\Type\NullableType.cs:Zeile 182.
bei NHibernate.Type.NullableType.NullSafeSet(IDbCommand st, Object value, Int32 index, Boolean[] settable, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Type\NullableType.cs:Zeile 122.
bei NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, Object value, Int32 index, Boolean[] settable, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Type\ManyToOneType.cs:Zeile 50.
bei NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id, Object[] fields, Object rowId, Boolean[] includeProperty, Boolean[][] includeColumns, Int32 table, IDbCommand statement, ISessionImplementor session, Int32 index) in p:\nhibernate-core\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:Zeile 2410.
As always in hard times I summoned the gooragle and the problem seems to be that the this.DiscriminateSubClassesOnColumn(processTypeId) adds a conflict with the this.References(x => x.ProcessType, processTypeId) mapping. When I remove the former the insert is successful but I want the subclass mapping AND I also need to be able to set the ProcessReferenceValues.ProcessType when adding new instances of ProcessReferenceValues to distinguish the subclasses.
The Question
Is it possible to discriminate subclasses on a column and at the same time referencing that same column on the same type?
Help very much appreciated, there's got to be a way to do this ...
thx in advance!
classes and mappings without the problem
// POCOs
class ProcessValue
{
public virtual int Id { get; set; }
public abstract ProcessValueType Type { get; }
}
class IntProcessValue : ProcessValue
{
public virtual int? Value { get; set; }
public override ProcessValueType Type { get { return ProcessValueType.Int; } }
}
class FloatProcessValue : ProcessValue
{
public virtual float? Value { get; set; }
public override ProcessValueType Type { get { return ProcessValueType.Float; } }
}
enum ProcessValueType : int
{
Int = 1,
Float = 2
}
// FluentNHibernate Mappings
class ProcessValueMap : ClassMap<ProcessValue>
{
public ProcessValueMap()
{
string processTypeId = "ProcessValueTypeId";
Id(x => x.Id);
// just so you can query by type enum also. Querying by clr Type is already implemented
Map(x => x.Type, processTypeId).CustomType<ProcessValueType>().ReadOnly().Access.None();
DiscriminateSubClassesOnColumn(processTypeId);
}
}
class IntProcessValueMap : SubclassMap<IntProcessValue>
{
public IntProcessValueMap()
{
Map(x => x.Value).Nullable();
DiscriminatorValue((int)ProcessValueType.Int);
}
}
class FloatProcessValueMap : SubclassMap<FloatProcessValue>
{
public FloatProcessValueMap()
{
Map(x => x.Value).Nullable();
DiscriminatorValue((int)ProcessValueType.Float);
}
}

ASP.NET Web Api System.Runtime.Serialization.SerializationException

I have a fully working MVC4 web site to which today I am trying to add a Web API though without success.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'System.Data.Entity.Infrastructure.DbQuery`1[[LeasingWeb.Models.Car, LeasingWeb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ArrayOfCar:http://schemas.datacontract.org/2004/07/LeasingWeb.Models' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
</ExceptionMessage>
<ExceptionType>
System.Runtime.Serialization.SerializationException
</ExceptionType>
<StackTrace>
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) at WriteCarDBToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract ) at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.<>c__DisplayClass7.<WriteToStreamAsync>b__6() at System.Threading.Tasks.TaskHelpers.RunSynchronously(Action action, CancellationToken token)
</StackTrace>
</InnerException>
</Error>
My objects are these:
public class Image
{
public int ID { get; set; }
[Required(ErrorMessage="Please select a car")]
[ForeignKey("Car")]
public int CarID { get; set; }
[DisplayName("Picture")]
[Required]
[FileExtensions(ErrorMessage = "Please specify a valid image file (.jpg, .jpeg, .gif or .png)", Extensions = ("jpg,png,jpeg"))]
public string Name { get; set; }
public virtual Car Car { get; set; }
}
public class Car
{
public int ID { get; set; }
[Required]
[DisplayName("Car Model")]
public string Name { get; set; }
[Required]
public string Company { get; set; }
[Required]
[DisplayName("Car Type")]
[ForeignKey("CarType")]
public int CarTypeID { get; set; }
[Required]
[Range(1,5)]
[DisplayName("Number Of Doors")]
public float NumDoors { get; set; }
[Required]
[Range(0, Int32.MaxValue)]
public float Acceleration { get; set; }
public virtual CarType CarType { get; set; }
}
public class CarType
{
[Key]
public int ID { get; set; }
[Required]
[DataType(DataType.Text)]
public string Type { get; set; }
}
And an object that holds them both:
public class CarDB
{
public IQueryable<Car> Cars { get; set; }
public IEnumerable<Image> Images { get; set; }
}
The API Controller:
public CarDB Get(int ID = -1)
{
CarDB car = new CarDB();
if (ID == -1)
{
car = new CarDB { Cars = db.Cars.Include(c => c.CarType), Images = db.Images };
}
else
{
car = new CarDB { Cars = db.Cars.Where(c => c.ID == ID).Include(c => c.CarType), Images = db.Images.Where(c => c.CarID == ID) };
}
return car;
}
Thanks to anyone that can help.
The issue here is the Cars member on the CarDB object. The DataContractSerializer special cases collection interfaces like IEnumerable and IList, but it doesn't special case derived interfaces like IQueryable. For these interfaces, they're treated as if the type were object and any implementations must be declared as known types.
You can try fixing this by changing the IQueryable<Car> member to IEnumerable<Car>.
I had this problem with legacy code using 30 tables with about 40 Foreign Keys with Lazy Loading. I found it easier, rather than adding more annotations to all the database classes, to just create a ViewModel with the fields that I wanted to be returned.
If the data being returned is complex, then I suggest using automapper.

IEnumerable and WCF - yet again

OK... I've looked on the web and found two possible solutions to my issue of not being able to return an IEnumerable type in a .Net 4.0 WCF service.
See below link. This is exactly what I'm getting when I am executing the WCF Test Client tool and trying to invoke a method.
https://connect.microsoft.com/wcf/feedback/details/336696/ienumerable-t-serialization-bug
Mind you, to be sure there is nothing wrong with my web service, I am able to return a type of this object for a single record, just not an IEnumerable.
Both solutions that I have tried, shown below do not work for me. I get the same error. This is driving me crazy. I know what the issue is, followed steps to circumvent the issue, but I am still getting the same error.
How can I resolve this?
This is the first solution I tried: Note that I even tried removing the "ToList" and "ToArray" on the last statement in each of the methods because it's implied already.
Interface
[OperationContract]
IList<Priority> GetPriorities();
Method
public IList<Priority> GetPriorities()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
IList<Priority> priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToList();
CloseConnection(DbContext);
return priority.ToList();
}
This is the second solution I tried:
Interface
[OperationContract]
Priority[] GetPriorities();
Method
public Priority[] GetPriorities()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
Priority[] priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToArray();
CloseConnection(DbContext);
return priority.ToArray();
}
Here it is with a List instead of an IList which still doesn't work.
Interface
[OperationContract]
List<Priority> GetPriorities();
Method
public List<Priority> GetPriorities()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
List<Priority> priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToList();
CloseConnection(DbContext);
return priority.ToList();
}
Notice that the below method works fine when retrieving just one object instead of a list.
[OperationContract]
Priority GetPriorityID(Int16 priorityid);
public Priority GetPriorityID(Int16 priorityid)
{
YeagerTechEntities DbContext = new YeagerTechEntities();
Priority priority = null;
var priorityEntity = (from p in DbContext.Priorities
where p.PriorityID == priorityid
select p).FirstOrDefault();
if (priorityEntity != null)
{
priority = new Priority();
priority.PriorityID = priorityEntity.PriorityID;
priority.Description = priorityEntity.Description;
CloseConnection(DbContext);
}
else
{
CloseConnection(DbContext);
throw new Exception("Priority " + priorityid + " not found!");
}
return priority;
}
The entire error msg from the wcf test client for the first method in this post is as follows. What is the resolution in order to be able to return a list of objects?
Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
An error occurred while receiving the HTTP response to http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ClientReliableChannelBinder1.RequestClientReliableChannelBinder1.OnRequest(TRequestChannel channel, Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder1.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.SecurityRequestSessionChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at IYeagerTechWcfService.GetPriorities()
at YeagerTechWcfServiceClient.GetPriorities()
Inner Exception:
The underlying connection was closed: An unexpected error occurred on a receive.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception:
An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
I modified my classes (see below), but am still getting the same exact error.
Surely, there must be someone who has tried this before where they get an object back from Entity Framework and want to pass it back as an IEnumerable. I'm very frustrated with this. Please help me out...
Based on my previous post, my classes are exactly the same with the following changes. I tried two methodologies.
Please refer to the first and second scenarios separately.
First scenario for Interface
I tried using just the Customer class and then an IEnumerable declaration of it.
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using YeagerTechModel;
namespace YeagerTechWcfService
{
//[ServiceKnownType(typeof(YeagerTechModel.Customer))]
[ServiceKnownType(typeof(IEnumerable<YeagerTechModel.Customer>))]
[ServiceContract]
public interface IYeagerTechWcfService
{
[OperationContract]
IEnumerable<Customer> GetCustomers();
[OperationContract]
Customer GetCustomerID(Int16 customerid);
It resides in my YeagerTechModel project in the same solution referenced by my web service (the other project in the same solution).
First scenario for Customer object
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace YeagerTechModel
{
[Serializable]
[DataContract]
public partial class Customer
{
public Customer()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CustomerID { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string Email { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Company { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string FirstName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string LastName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address1 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address2 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string City { get; set; }
[StringLength(2)]
[DataType(DataType.Text)]
[DataMember]
public string State { get; set; }
[StringLength(10)]
[DataType(DataType.Text)]
[RegularExpression(#"^\d{5}(-\d{4})?$")]
[DataMember]
public string Zip { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
public string HomePhone { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
[DataMember]
public string CellPhone { get; set; }
[StringLength(100)]
[DataType(DataType.Url)]
[DataMember]
public string Website { get; set; }
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string IMAddress { get; set; }
[DataMember]
public System.DateTime CreatedDate { get; set; }
[DataMember]
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
Second scenario for interface:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using YeagerTechModel;
namespace YeagerTechWcfService
{
[ServiceContract]
public interface IYeagerTechWcfService
{
[OperationContract]
IEnumerable<Customer> GetCustomers();
[OperationContract]
Customer GetCustomerID(Int16 customerid);
Second scenario for Customer object
I have tried using just the Customer class and then an IEnumerable declaration of it at the bottom of this class.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace YeagerTechModel
{
[KnownTypeAttribute("KnownTypes")]
[Serializable]
[DataContract]
public partial class Customer
{
public Customer()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CustomerID { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string Email { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Company { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string FirstName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string LastName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address1 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address2 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string City { get; set; }
[StringLength(2)]
[DataType(DataType.Text)]
[DataMember]
public string State { get; set; }
[StringLength(10)]
[DataType(DataType.Text)]
[RegularExpression(#"^\d{5}(-\d{4})?$")]
[DataMember]
public string Zip { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
public string HomePhone { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
[DataMember]
public string CellPhone { get; set; }
[StringLength(100)]
[DataType(DataType.Url)]
[DataMember]
public string Website { get; set; }
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string IMAddress { get; set; }
[DataMember]
public System.DateTime CreatedDate { get; set; }
[DataMember]
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual ICollection<Project> Projects { get; set; }
static Type[] KnownTypes()
{
return new Type[] { typeof(IEnumerable<Customer>) };
}
}
I tried:
return customer;
return customer.ToList();
return customer.ToArray();
public IEnumerable<Customer> GetCustomers()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
IEnumerable<Customer> customer = DbContext.Customers.Where(p => p.CustomerID > 0);
CloseConnection(DbContext);
return customer;
}
The problem seems to be a serialization issue when trying to pass back the Customer object which is part of an Entity Framework model. There has to be a documented way of passing back an object of this type which is derived from an Entity Framework model.
Where is it????
Here is the latest of what I tried and am still getting the same exact error....
namespace YeagerTechWcfService
{
[ServiceContract]
public interface IYeagerTechWcfService
{
[OperationContract]
List<Customer> GetCustomers();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace YeagerTechModel
{
[Serializable]
[DataContract]
public partial class Customer
{
public Customer()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CustomerID { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string Email { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Company { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string FirstName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string LastName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address1 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address2 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string City { get; set; }
[StringLength(2)]
[DataType(DataType.Text)]
[DataMember]
public string State { get; set; }
[StringLength(10)]
[DataType(DataType.Text)]
[RegularExpression(#"^\d{5}(-\d{4})?$")]
[DataMember]
public string Zip { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
public string HomePhone { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
[DataMember]
public string CellPhone { get; set; }
[StringLength(100)]
[DataType(DataType.Url)]
[DataMember]
public string Website { get; set; }
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string IMAddress { get; set; }
[DataMember]
public System.DateTime CreatedDate { get; set; }
[DataMember]
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public List<Customer> GetCustomers()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
List<Customer> customer = DbContext.Customers.Where(p => p.CustomerID > 0).ToList();
return customer.ToList();
}
The answer was as simple as setting a property to false before making my EF call to the database.
DbContext.Configuration.ProxyCreationEnabled = false;
EF automatically generates a proxy class. Dynamic Proxies – They don’t play nice over the wire – Turn these off (ContextOptions.ProxyCreationEnabled == false).