Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default mappingschema is nog the first in the schema list #4492

Open
linmic30 opened this issue May 2, 2024 · 4 comments
Open

Default mappingschema is nog the first in the schema list #4492

linmic30 opened this issue May 2, 2024 · 4 comments

Comments

@linmic30
Copy link

linmic30 commented May 2, 2024

When adding a new metadata reader to the default mappingschema will not result in the use of this metadata reader. This is because the default schema is not the first in the schema list. As shown in this discussion, the workaround is to add the default schema to the dataoptions. However, imo, this is not the cleanest way to go. My expectation is that the default schema is the first in the list of schemas.

Steps to reproduce

First we create the DataOptions and then add the new metadata reader to the default schema.

DbContextOptions = new DbContextOptions(connectionString, siteID); 

LinqToDB.Mapping.MappingSchema.Default.AddMetadataReader(new LinqToDbProvider(DbContextOptionsBrouwen.IsSite1 ? typeof(ColumnSite1Attribute) : typeof(ColumnSite2Attribute))); 

public DbContextOptions(string connectionString, string siteID)  
{ 
       SiteId = siteID; IsSite1 = siteID == "6100"; 
       DbOptions = new DataOptions().UseSqlServer(connectionString, SqlServerVersion.v2012, SqlServerProvider.SystemDataSqlClient); 
}

LinqToDbProvider implements IMetadataReader.
When going through the code the first two schema's in the schema list from de MappingSchema class will be for sql server and sqlserverversion. These two are of the type LockedSchemaMapping After these two you will find the default mappingschema.

Environment details

Linq To DB version: 5.4.1

Operating system: Windows 11

.NET Version: .net 8.0

@MaceWindu
Copy link
Contributor

That is correct behavior. Default schema tried last to allow user to override it using more specific schema.

@linmic30
Copy link
Author

linmic30 commented May 2, 2024

The problem only is the codes never gets to the default schema because of the following code in the MappingSchema class:

		/// Gets attributes of specified type, associated with specified type.
		/// </summary>
		/// <typeparam name="T">Mapping attribute type (must inherit <see cref="MappingAttribute"/>).</typeparam>
		/// <param name="type">Attributes owner type.</param>
		/// <returns>Attributes of specified type.</returns>
		private T[] GetAllAttributes<T>(Type type)
			where T : MappingAttribute
		{
			return Schemas[0].MetadataReader?.GetAttributes<T>(type) ?? Array<T>.Empty;
		}

		/// <summary>
		/// Gets attributes of specified type, associated with specified type member.
		/// </summary>
		/// <typeparam name="T">Mapping attribute type (must inherit <see cref="MappingAttribute"/>).</typeparam>
		/// <param name="type">Member's owner type.</param>
		/// <param name="memberInfo">Attributes owner member.</param>
		/// <returns>Attributes of specified type.</returns>
		private T[] GetAllAttributes<T>(Type type, MemberInfo memberInfo)
			where T : MappingAttribute
		{
			return Schemas[0].MetadataReader?.GetAttributes<T>(type, memberInfo) ?? Array<T>.Empty;
		}

With using Schema[0] it always takes the first of the list. What we see is that AddSqlServer on the DataOptions adds two extra schemas to the beginning of this list. Forcing the default schema to the last position of the schema list.

@MaceWindu
Copy link
Contributor

Schemas[0].MetadataReader is not just first metadata reader actually, but instance of https://github.com/linq2db/linq2db/blob/master/Source/LinqToDB/Metadata/MetadataReader.cs which aggregates access to all metadata readers in MappingSchema on schema creation or when you add additional provider to current schema. If you add provider to child schema after current schema created - it will not affect current schema:

var ms = new MappingSchema();
// ms use metadata providers from Default schema

ms.AddMetadataReader(provider1);
// ms now use provider1 and providers from Default schema
// with provider1 having higher priority

DefaultSchema.AddMetadataReader(provider2);
// default schema now have provider2 with highest priority alongside with other providers it already had
// but ms schema still works with provider1 and old set of providers, copied from default schema during
// ms schema creation

@linmic30
Copy link
Author

linmic30 commented May 2, 2024

Oke, I did mis the part that the default will be used when no more specific schema is defined. But, when the code that is in the original post is used, our own provider is not being called. The breakpoints in the getattributes are not being hit.

Imo this is because the default schema with our own provider is in the last place of the schema list. And with the code that is now in the library only the first schema will be used.

What is also a bit weird is that there will be two extra schema's without them being created knowingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants