Tag Archives: Entity Framework

Hunting “EntityType ‘Image’ has no key defined. Define the key for this EntityType.” problem

Few weeks back I was hired to debug the above mentioned problem. The application was using Entity Framework 5 and Firebird as a database. The message says clearly what’s wrong. How hard can it be to fix the problem, right? I was thinking the same. And how wrong I was.

After receiving the sources and quickly extracting the bare metal with error I started looking for Image type. And there it was. The class had Id property, so the key was kind of there. The default convention should be able to find. Let’s look at configuration, if there’s something suspicious. And even better, the HasKey call is there. OK, maybe there’s some magic in OnModelCreating. Nope. Everything as expected.

By the way, the exact error was:

ModelValidationException: One or more validation errors were detected during model generation:

	System.Data.Entity.Edm.EdmEntityType: : EntityType 'Image' has no key defined. Define the key for this EntityType.
	System.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'Images' is based on type 'Image' that has no keys defined.

That’s the overview. Next two hours I was trying to changes something here and there and make it fail, so I knew it’s doing what it should do. Removing some stuff that might break something. And still no luck. But then something caught my eye. The error is talking about “Image” type. My type from database is “IMAGE” (the mapping and classes were generated by Entity Framework Power Tools and because of how SQL standard defines non-quoted names, it’s by default all uppercase). Yes, there was a property added to some entity that had a type Image, I mean System.Drawing.Image.

So quickly adding Ignore into OnModelCreating and I was done. Lesson learned.

Entity Framework is open source, why not SqlClient?

If you’re watching at least a little what’s going on in .NET world you noticed that Entity Framework is open source for couple months now. That’s a good thing.

On the other had there are still some pieces of the complete stack that are not open source. The one that I’m missing most is SqlClient. I’m writing provider for Firebird and although the MSDN documentation contains a lot of content sometimes it’s not obvious how things should behave. Then the SqlClient‘s behavior is (at least by me) taken as de-facto standard. I think everybody expects behavior that adheres to it. Over the last few years I’ve spent maybe thousands of hours trying things with SqlClient and ILDASM-ing into internals. But it could be easier if you could just step into the code and see the behavior, variables, … Also other people might look at the code and instead of just reporting bug posting also related info where to find the proper implementation or how it differs internally.

I wish to go back to this post in the foreseeable future and happily strike-though the complete text and just say that SqlClient is open source too.

Entity SQL and spatial data

When the Entity Framework was first introduced it came with (basically) two flavors of querying. LINQ to Entities and Entity SQL (ESQL). I’m not going to describe the history here. But as LINQ (any LINQ) gained popularity it was obvious, that LINQ to Entities is a future (though it had initially small deficit compared to Entity SQL). I even on my courses recommend using LINQ to Entities whenever possible and I’m also showing some dynamic querying where normally people start concatenating ESQL strings.

Recently Entity Framework added support for spatial data (and enums, …). All examples I’ve ever seen around spatial data and Entity Framework were using LINQ (obviously). Only few weeks ago I realized how the querying should work with Entity SQL. As it turned out spatial data are not first class citizen in Entity SQL world. There’s no literal for i.e. point. But canonical functions are here to save you. There’s a bunch of these spatial data related. What we’re looking for though is GeometryFromText/
GeographyFromText. With these you can construct Geometry/Geography datatype from well-known text (WKT) and use it in query.

I’ve never used Entity SQL query in any real-world application I created. I’m too afraid of typos etc. But I did a lot of magic with expression trees. :) Wondering what percentage of people using Entity Framework is using Entity SQL and whether there are some scenarios that are crazy hard in LINQ…

Changing entity names (i.e. removing prefix) in Entity Framework’s EDMX in batch

Few years back I wrote a similar post Making names of entities (or any identifiers) in Entity Framework model “code and developer friendly” (= not uppercase), but as the time goes, it’s now little bit outdated. But yesterday Julie Lerman, while trying to find solution for one particular question, dug it out. As I was also then introduced to problem the solution there was indeed a good way to go. But to use it, it needed to be updated for current version of Entity Framework (version 5 in time of writing).

So here it is. Slightly refactored. Because the question was originally interested in stripping some prefix (tbl to be precise) the code is doing exactly that. But if you want different prefix be stripped, just change the PREFIX constant. Of if you want something more change the transformation function completely (ideally should be idempotent).

static void TransformEDMXEntities(string inputFile, string outputFile)
{
	XDocument xdoc = XDocument.Load(inputFile);

	const string CSDLNamespace = "http://schemas.microsoft.com/ado/2009/11/edm";
	const string MSLNamespace = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
	const string DesignerNamespace = "http://schemas.microsoft.com/ado/2009/11/edmx";
	XElement csdl = xdoc.Descendants(XName.Get("Schema", CSDLNamespace)).First();
	XElement msl = xdoc.Descendants(XName.Get("Mapping", MSLNamespace)).First();
	XElement designerDiagram = xdoc.Descendants(XName.Get("Designer", DesignerNamespace)).First();

	Func<string, string> transformation = (string input) =>
	{
		const string PREFIX = "tbl";
		Regex re = new Regex(string.Format(@"{0}(\w+)", Regex.Escape(PREFIX)), RegexOptions.None);
		return re.Replace(input, new MatchEvaluator(
			(Match m) =>
			{
				return m.Groups[1].Value;
			}));
	};

	TransformCSDL(CSDLNamespace, csdl, transformation);
	TransformMSL(MSLNamespace, msl, transformation);
	TransformDesigner(DesignerNamespace, designerDiagram, transformation);

	using (XmlTextWriter writer = new XmlTextWriter(outputFile, Encoding.Default))
	{
		xdoc.WriteTo(writer);
	}
}

static void TransformDesigner(string DesignerNamespace, XElement designerDiagram, Func<string, string> transformation)
{
	foreach (var item in designerDiagram.Elements(XName.Get("EntityTypeShape", DesignerNamespace)))
	{
		item.Attribute("EntityType").Value = transformation(item.Attribute("EntityType").Value);
	}
}

static void TransformMSL(string MSLNamespace, XElement msl, Func<string, string> transformation)
{
	foreach (var entitySetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("EntitySetMapping", MSLNamespace)))
	{
		entitySetMapping.Attribute("Name").Value = transformation(entitySetMapping.Attribute("Name").Value);
		foreach (var entityTypeMapping in entitySetMapping.Elements(XName.Get("EntityTypeMapping", MSLNamespace)))
		{
			entityTypeMapping.Attribute("TypeName").Value = transformation(entityTypeMapping.Attribute("TypeName").Value);
		}
	}
}

static void TransformCSDL(string CSDLNamespace, XElement csdl, Func<string, string> transformation)
{
	foreach (var entitySet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("EntitySet", CSDLNamespace)))
	{
		entitySet.Attribute("Name").Value = transformation(entitySet.Attribute("Name").Value);
		entitySet.Attribute("EntityType").Value = transformation(entitySet.Attribute("EntityType").Value);
	}
	foreach (var associationSet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("AssociationSet", CSDLNamespace)))
	{
		foreach (var end in associationSet.Elements(XName.Get("End", CSDLNamespace)))
		{
			end.Attribute("EntitySet").Value = transformation(end.Attribute("EntitySet").Value);
		}
	}

	foreach (var entityType in csdl.Elements(XName.Get("EntityType", CSDLNamespace)))
	{
		entityType.Attribute("Name").Value = transformation(entityType.Attribute("Name").Value);
	}
	foreach (var association in csdl.Elements(XName.Get("Association", CSDLNamespace)))
	{
		foreach (var end in association.Elements(XName.Get("End", CSDLNamespace)))
		{
			end.Attribute("Type").Value = transformation(end.Attribute("Type").Value);
		}
	}
}

When you (re)generate your EDMX file, you can unleash this code (I think simple console app will be best for it), do the transformation and reopen the file in Visual Studio. If the transformation is idempotent you’re ready to go, else you’ll need to do some manual merging with previous version.

Of course you can go further and change also names on i.e. navigational properties and so on. In fact in original post in comments you can find inspiration for it.

Enjoy.

Custom transactions in Entity Framework 6

Entity Framework 6 will come with a nice feature of being able to use custom transactions. You can either manually start new one with some isolation level (in fact this was possible even before, just little bit more code) or – and this is really nice, because I had questions about this (and did some custom hacks in Firebird’s provider) couple of times. So I like it. And I like it also because finally the transactions are (at least in my eyes) of same importance as connections (where the support was good before).

There’s one thing, I think, that will make it even better. Something like “transaction factory”. The motivation behind is, that you often need to have a specific set up for the transactions and use it always (with maybe few exceptions). The UseTransaction method seems to have one drawback: you need to access the connection (that means either from context or from other place where you stored it) and start the transaction. Later commit or rollback it. You can do it easily for SaveChanges/SaveChangesAsync. But for queries? You’ll need to create and use your own plumbing/infrastructure throughout the code. But adding some point, where you can plug in (and also though resolver/configuration), might make it very easy.

// i.e. Func<DbConnection, DbTransaction>
dbContextInstance.TransactionFactory = connection => (connection as MyDbConnection).BeginTransaction(/* some crazy setup */);  // MyDbConnection is the actual store connection

Of course, you might say: “And who is going to commit/rollback it?”. You might opt-in for default behavior – no error = commit, rollback else. Or handle it manually in some OnCommit/OnRollback events (or factory again to make it more enterprise-ish 8-)).

Anyway I don’t want to discuss all the details of actual implementation or how it aligns to current state. Just a opinion and high level overview of my thoughts.

If you might have questions or need some examples or motivations, let me know in comments. I have handful of these.

Custom conventions in Entity Framework 6 helping Firebird – part 2

Few days ago I wrote a post “Custom conventions in Entity Framework 6 helping Firebird“. Arthur Vickers from Entity Framework team had a good question whether it works also for columns and tables that are generated by Entity Framework (like join tables for M:N, FK columns (if not in model), etc.). And it actually does not. :) For this you have to dig a little bit deeper and use model-based convention. For this type of convention you have to write a class as there’s (currently, alpha 3) no way to do it using fluent API in a lightweight way (and I would not expect this to change, this isn’t common scenario).

Anyway for properties to work you have to implement IDbConvention<EdmProperty> and for table IDbConvention<EntityType> (not EntitySet, you need to be able to see whether somebody set the table name already or not which for me is easier from EntityType type). Don’t ask me how I found this. A lot of trial and error. And actually a lot of memories from around 2010 and Entity Framework v1 (link, link (anybody here ever explored MetadataProperties?)) :) .

class FirebirdFriendlyModelConvention : IDbConvention<EdmProperty>, IDbConvention<EntityType>
{
	public void Apply(EdmProperty dbDataModelItem, EdmModel model)
	{
		var preferredName = (string)dbDataModelItem.Annotations.First(x => x.Name == "PreferredName").Value;
		if (preferredName == dbDataModelItem.Name)
			dbDataModelItem.Name = FirebirdNamingConvention.CreateName(dbDataModelItem.Name);
	}

	EntityType GetRootType(EntityType entityType)
	{
		if (entityType.BaseType != null)
			return GetRootType((EntityType)entityType.BaseType);
		return entityType;
	}

	string GetTableName(ICollection<DataModelAnnotation> anotations)
	{
		var anotation = anotations.FirstOrDefault(x => x.Name == "TableName");
		if (anotation == null)
			return null;
		return (string)anotation.Value;
	}

	public void Apply(EntityType dbDataModelItem, EdmModel model)
	{
		var entitySet = model.Containers.First().EntitySets.SingleOrDefault(e => e.ElementType == GetRootType(dbDataModelItem));
		var tableName = GetTableName(dbDataModelItem.Annotations);
		if (tableName == null)
		{
			tableName = FirebirdNamingConvention.CreateName(dbDataModelItem.Name);
			entitySet.GetType().GetProperty("Table").SetValue(entitySet, tableName);
		}
	}
}

As you can see it’s not magic, if you know where to look at. Because the Table property is currently (alpha 3) not public I was forced to use reflection. There’s the related work item.

With this conventions, hopefully, all the tables and columns, except specified explicitly, will be renamed to “common” Firebird naming.