I want to map a SQL FileTable with DataAccess. This works in the designer but the fluent notation doesn't work. I cannot map the Id property (path_locator) as IsIdentity because SqlHierarchyId cannot be defined as IsIdentity.
Is there a known workaround?
configuration.HasProperty(x => x.Id).IsIdentity<GenericPropertyConfiguration>().WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("path_locator").IsNotNullable(); // this is not allowed
If I omit the IsIdentity, Data Access looks for a voa_keygen table...
Greetings,
Florian
16 Answers, 1 is accepted
Can you please give me a hint on this. It is a showstopper in our company, as I assumed FileTable mappings are possible with Telerik.DataAccess.
Basically I need the example given in the post http://www.telerik.com/forums/error-while-trying-to-map-sql2012-filetable
in a DataAccess.Fluent version.
Thanks a lot!
To map a HierarchyId column type as Identity Column with fluent mapping you should only specify the column type for the property as 'hierarchyId'.
For example the mapping for this class:
public class Employee{ public SqlHierarchyId Id { get; set; } public string Name { get; set; }}Should look like this:
MappingConfiguration<Employee> configuration = new MappingConfiguration<Employee>();configuration.MapType(x => new { Id = x.Id, Name = x.Name }).ToTable("EmployeeWithHierarchyID");configuration.HasProperty<Employee>(x => x.Id).HasColumnType("hierarchyid").IsIdentity();configuration.HasProperty(x => x.Name).ToColumn("Name");I hope that helps.
Regards,
Boris Georgiev
Telerik
Hi Boris
Thanks for your answer. I'm sorry, but your method doesn't seem to work. Have you actually tried this?
(I have tried it with Microsoft.SqlServer.Types 10 and 12 version).
I receive a compilation error:
Error CS1662:Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type Reber.Document C:\Daten\Source\zh\meddb-dms\Reber.Document\DbMetadataSource.cs 75Error CS0029:Cannot implicitly convert type 'Microsoft.SqlServer.Types.SqlHierarchyId' to 'System.Collections.Generic.IList<byte>'C:\Daten\Source\zh\meddb-dms\Reber.Document\DbMetadataSource.cs 75Here is my complete mapping (please focus on the Id property, maybe the rest has to be reviewed):
public MappingConfiguration<FileStore> GetFileStoreMappingConfiguration(){ MappingConfiguration<FileStore> configuration = this.GetFileStoreClassConfiguration(); this.PrepareFileStorePropertyConfigurations(configuration); this.PrepareFileStoreAssociationConfigurations(configuration); return configuration;}public MappingConfiguration<FileStore> GetFileStoreClassConfiguration(){ MappingConfiguration<FileStore> configuration = new MappingConfiguration<FileStore>(); configuration.MapType().WithConcurencyControl(OptimisticConcurrencyControlStrategy.Changed).ToTable("FileStore"); return configuration;}public void PrepareFileStorePropertyConfigurations(MappingConfiguration<FileStore> configuration){ configuration.HasProperty<FileStore>(x => x.Id).HasColumnType("hierarchyid").IsIdentity(); //configuration.HasProperty(x => x.Id).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("path_locator").IsNotNullable().HasColumnType("hierarchyid"); configuration.HasProperty(x => x.StreamId).IsIdentity().WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("stream_id").IsNotNullable().HasColumnType("Guid"); configuration.HasProperty(x => x.FileStream).WithDataAccessKind(DataAccessKind.ReadWrite).ToColumn("file_stream").IsNullable().HasColumnType("varbinary"); configuration.HasProperty(x => x.IsDirectory).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_directory").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.IsArchive).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_archive").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.IsHidden).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_hidden").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.IsOffline).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_offline").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.IsReadonly).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_readonly").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.IsSystem).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_system").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.IsTemporary).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("is_temporary").IsNotNullable().HasColumnType("bit").HasPrecision(0).HasScale(0); configuration.HasProperty(x => x.FileType).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("file_type").IsNullable().HasColumnType("nvarchar").HasLength(255); configuration.HasProperty(x => x.Name).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("name").IsNotNullable().HasColumnType("nvarchar").HasLength(255); configuration.HasProperty(x => x.PathLocator).AsTransient();//.WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("path_locator").IsNotNullable().HasColumnType("hierarchyid"); configuration.HasProperty(x => x.ParentPathLocator).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("parent_path_locator").IsNullable().HasColumnType("hierarchyid"); configuration.HasProperty(x => x.CachedFileSize).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("cached_file_size").IsNullable().HasColumnType("bigint"); configuration.HasProperty(x => x.CreationTime).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("creation_time").IsNotNullable().HasColumnType("datetimeoffset"); configuration.HasProperty(x => x.LastAccessTime).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("last_access_time").IsNullable().HasColumnType("datetimeoffset"); configuration.HasProperty(x => x.Parent).AsTransient(); configuration.HasProperty(x => x.LastWriteTime).WithDataAccessKind(DataAccessKind.ReadOnly).ToColumn("last_write_time").IsNullable().HasColumnType("datetimeoffset");}public partial class FileStore : IEntityWithTypedId<SqlHierarchyId>{ public virtual SqlHierarchyId Id { get; set; } public virtual byte[] FileStream { get; set; } public virtual string Name { get; set; } public virtual SqlHierarchyId PathLocator { get; set; } public virtual SqlHierarchyId ParentPathLocator { get; set; } public virtual string FileType { get; set; } public virtual long? CachedFileSize { get; set; } public virtual DateTimeOffset CreationTime { get; set; } public virtual DateTimeOffset LastWriteTime { get; set; } public virtual DateTimeOffset? LastAccessTime { get; set; } public virtual bool IsDirectory { get; set; } public virtual bool IsOffline { get; set; } public virtual bool IsHidden { get; set; } public virtual bool IsReadonly { get; set; } public virtual bool IsArchive { get; set; } public virtual bool IsSystem { get; set; } public virtual bool IsTemporary { get; set; } public virtual FileStore Parent { get; set; } public virtual IList<FileStore> FileStores { get; set; } public Guid StreamId { get; set; }}Hi Boris
I'm still waiting for a working solution. Meanwhile I have found some kind of workaround, but im not sure if this method has some sideeffects:
public partial class FileStore : IEntityWithTypedId<SqlHierarchyId>{ private SqlHierarchyId id; public virtual SqlHierarchyId Id { get { return this.id; } set { this.id = value; } } public virtual BinaryStream FileStream { get; set; } // more properties...}Mapping:
configuration .HasPrimitiveMember("id", "Id") .IsIdentity() .WithDataAccessKind(DataAccessKind.ReadOnly) .IsNotNullable() .ToColumn("path_locator") .HasColumnType("hierarchyid"); configuration .HasProperty(x => x.FileStream) .WithDataAccessKind(DataAccessKind.ReadWrite) .ToColumn("file_stream") .IsNullable();This works at least for read-operations. But when I try to insert a file, I ran into a new problem:
A SQL-FileTable has a check-constraint for the "file_stream" column (varbinary(max). I must not be null: you must insert at least 0x.
Using your BinaryStream type for the "FileStream" property in my "FileStore" class above, this will not work. Data Access seems to insert the row first and then writes the stream -> this is not allowed by the FileTable (and I cannot remove the constraint as it is by design).
I'm using this method to insert a new file:
developer-guide-domain-model-managing-advanced-working-with-streams​
using (var db = new Reber.Document.Db()){ var file = new FileStore(); file.Id = db.FileStores.First(x => x.IsDirectory).Id.GetDescendant(SqlHierarchyId.Null, SqlHierarchyId.Null); file.Name = "test.txt"; var attachedFile = db.AttachCopy(file); db.FlushChanges(); // exception here using (FileStream stream = File.OpenRead(@"C:\temp\AllTags.docx")) { byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { attachedFile.FileStream.Write(buffer, 0, bytesRead); } } db.SaveChanges();}Exception details:
Die MedDB.Test.TestDataAccess.CanUseDocumentDataContext-Testmethode hat eine Ausnahme ausgelöst: Telerik.OpenAccess.Exceptions.DataStoreException: Insert of '2059671172-/9095764594888.222387776954401.2966721089/1/' failed: Telerik.OpenAccess.RT.sql.SQLException: Der Vorgang hat einen Fehler bei einer CHECK-Einschränkung für eine 'FileTable' verursacht. Ein Dateieintrag darf keinen NULL-Wert für den der Zeile zugeordneten Datenstrom enthalten. Fügen Sie Dateidaten ein, oder verwenden Sie '0x', um eine Datei mit der Länge 0 einzufügen. ---> System.Data.SqlClient.SqlException: Der Vorgang hat einen Fehler bei einer CHECK-Einschränkung für eine 'FileTable' verursacht. Ein Dateieintrag darf keinen NULL-Wert für den der Zeile zugeordneten Datenstrom enthalten. Fügen Sie Dateidaten ein, oder verwenden Sie '0x', um eine Datei mit der Länge 0 einzufügen. bei System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) bei System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) bei System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) bei System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) bei System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() bei System.Data.SqlClient.SqlDataReader.get_MetaData() bei System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) bei System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest) bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) bei System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) bei System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) bei System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) bei OpenAccessRuntime.CommandWrapper.ExecuteReader(CommandBehavior behavior) bei Telerik.OpenAccess.Runtime.Logging.LoggingDbCommand.ExecuteDbDataReader(CommandBehavior behavior) bei System.Data.Common.DbCommand.ExecuteReader() bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.CommandImp.ExecuteReader() bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute(Nullable`1 commandTimeout) --- Ende der internen Ausnahmestapelüberwachung --- bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute(Nullable`1 commandTimeout) bei OpenAccessRuntime.Relational.conn.PooledPreparedStatement.execute(Nullable`1 commandTimeout) bei OpenAccessRuntime.Relational.RelationalStorageManager.generateInserts(NewObjectOID oid, Int32 index, ClassMetaData cmd, PersistGraph graph, Int32[] fieldNos, CharBuf s, Object[] oidData, IntArray toUpdateIndexes, BatchControlInfo batchControl)INSERT INTO [FileStore] ([name]) VALUES (?)(set event logging to all to see parameter values) Telerik.OpenAccess.RT.sql.SQLException: Der Vorgang hat einen Fehler bei einer CHECK-Einschränkung für eine 'FileTable' verursacht. Ein Dateieintrag darf keinen NULL-Wert für den der Zeile zugeordneten Datenstrom enthalten. Fügen Sie Dateidaten ein, oder verwenden Sie '0x', um eine Datei mit der Länge 0 einzufügen. ---> System.Data.SqlClient.SqlException: Der Vorgang hat einen Fehler bei einer CHECK-Einschränkung für eine 'FileTable' verursacht. Ein Dateieintrag darf keinen NULL-Wert für den der Zeile zugeordneten Datenstrom enthalten. Fügen Sie Dateidaten ein, oder verwenden Sie '0x', um eine Datei mit der Länge 0 einzufügen. bei System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) bei System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) bei System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) bei System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) bei System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() bei System.Data.SqlClient.SqlDataReader.get_MetaData() bei System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) bei System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest) bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) bei System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) bei System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) bei System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) bei OpenAccessRuntime.CommandWrapper.ExecuteReader(CommandBehavior behavior) bei Telerik.OpenAccess.Runtime.Logging.LoggingDbCommand.ExecuteDbDataReader(CommandBehavior behavior) bei System.Data.Common.DbCommand.ExecuteReader() bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.CommandImp.ExecuteReader() bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute(Nullable`1 commandTimeout) --- Ende der internen Ausnahmestapelüberwachung --- bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute(Nullable`1 commandTimeout) bei OpenAccessRuntime.Relational.conn.PooledPreparedStatement.execute(Nullable`1 commandTimeout) bei OpenAccessRuntime.Relational.RelationalStorageManager.generateInserts(NewObjectOID oid, Int32 index, ClassMetaData cmd, PersistGraph graph, Int32[] fieldNos, CharBuf s, Object[] oidData, IntArray toUpdateIndexes, BatchControlInfo batchControl) ---> Telerik.OpenAccess.RT.sql.SQLException: Der Vorgang hat einen Fehler bei einer CHECK-Einschränkung für eine 'FileTable' verursacht. Ein Dateieintrag darf keinen NULL-Wert für den der Zeile zugeordneten Datenstrom enthalten. Fügen Sie Dateidaten ein, oder verwenden Sie '0x', um eine Datei mit der Länge 0 einzufügen. ---> System.Data.SqlClient.SqlException: Der Vorgang hat einen Fehler bei einer CHECK-Einschränkung für eine 'FileTable' verursacht. Ein Dateieintrag darf keinen NULL-Wert für den der Zeile zugeordneten Datenstrom enthalten. Fügen Sie Dateidaten ein, oder verwenden Sie '0x', um eine Datei mit der Länge 0 einzufügen. bei System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) bei System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) bei System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) bei System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, ref Boolean dataReady) bei System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() bei System.Data.SqlClient.SqlDataReader.get_MetaData() bei System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) bei System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, ref Task task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest) bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, ref Task task, Boolean asyncWrite) bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) bei System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) bei System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) bei System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) bei OpenAccessRuntime.CommandWrapper.ExecuteReader(CommandBehavior behavior) bei Telerik.OpenAccess.Runtime.Logging.LoggingDbCommand.ExecuteDbDataReader(CommandBehavior behavior) bei System.Data.Common.DbCommand.ExecuteReader() bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.CommandImp.ExecuteReader() bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute(Nullable`1 commandTimeout) --- Ende der inneren Ausnahmestapelüberwachung --- bei Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute(Nullable`1 commandTimeout) bei OpenAccessRuntime.Relational.conn.PooledPreparedStatement.execute(Nullable`1 commandTimeout) bei OpenAccessRuntime.Relational.RelationalStorageManager.generateInserts(NewObjectOID oid, Int32 index, ClassMetaData cmd, PersistGraph graph, Int32[] fieldNos, CharBuf s, Object[] oidData, IntArray toUpdateIndexes, BatchControlInfo batchControl) --- Ende der inneren Ausnahmestapelüberwachung --- bei OpenAccessRuntime.ExceptionWrapper.Throw() bei OpenAccessRuntime.DataObjects.OpenAccessPersistenceManagerImp.handleException(Exception x, Boolean needsRollback) bei OpenAccessRuntime.DataObjects.OpenAccessPersistenceManagerImp.flushRetainState() bei OpenAccessRuntime.DataObjects.UnsynchronizedPMProxy.flush(Boolean retainState) bei OpenAccessRuntime.EnlistableObjectScope.FlushChanges(Boolean releaseMemory) bei Telerik.OpenAccess.OpenAccessContextBase.FlushChanges(Boolean releaseMemory) bei Telerik.OpenAccess.OpenAccessContextBase.FlushChanges() bei MedDB.Test.TestDataAccess.CanUseDocumentDataContext() in TestDataAccess.cs: line 102.Please help me with this. A byte[] is not an option (only if I can do some kind of lazy-loading for this property).
Greetings,
Florian
You are on the right track and you had found the right solution for the issue with the byte array. BinaryStream type is a special type that exposes a stream around a database binary field and it is provided by Telerik Data Access for working with varbinary(max) columns.
From the third code snippet which you had sent, it looks like you are trying to insert the row with the FlushChanges() method in the database and if the file_stream column is nullable it should insert a null value in the column. From the first and the second code snippet, it looks like your mapping is also right. Could you sent us the sample application and the database script so we could try to reproduce the issue in our test environment?
I am looking forward to hearing from you.
Regards,
Boris Georgiev
Telerik
Hi Boris
The file_stream column is nullable indeed, but has a check-constraint by design (see the Microsoft FileTable documentation). So you can only insert null if you try to create a directory. Basically I'm trying to map a FileTable (with a predefined schema) in DataAccess. I'm going to make you a sample and upload it, but to give you an idea you could just create a filetable like this and map it in DataAccess:
-- CONFIGURE FIREWALL https://msdn.microsoft.com/en-us/library/dd283098.aspx-- Allow TCP inbound, 139 and 445-- adapt directories, database etc below.-- enable Filestream on instanceEXEC sp_configure filestream_access_level, 2RECONFIGUREGO-- add filestream group to existing databaseALTER DATABASE MyRepositoryADD FILEGROUP FileStoreFileGroup CONTAINS FILESTREAM GO-- the following statement only works if nobody is connected!ALTER DATABASE MyRepository SET FILESTREAM ( NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME = N'MyRepository' );GOALTER DATABASE MyRepositoryADD FILE ( NAME = 'FileStore', FILENAME = 'C:\FileStore' )TO FILEGROUP FileStoreFileGroup;GO-- Check the Filestream OptionsSELECT DB_NAME(database_id),non_transacted_access,non_transacted_access_descFROM sys.database_filestream_options;GOUSE MyRepositoryIF OBJECT_ID('dbo.FileStore', 'U') IS NOT NULL DROP TABLE dbo.FileStoreGO-- add filetabe: user will access the file in share \\computername\db-instance (mssqlserver)\MyRepository\Documents-- i.e. \\server-xy\mssqlserver\MyRepository\DocumentsCREATE TABLE FileStore AS FileTableWITH (FileTable_Directory = 'Documents');GOSELECT DB_NAME ( database_id ), directory_name FROM sys.database_filestream_options;GO--View all objects for all filetables, unsortedSELECT * FROM sys.filetable_system_defined_objects;GO--View sorted list with friendly namesSELECT OBJECT_NAME(parent_object_id) AS 'FileTable', OBJECT_NAME(object_id) AS 'System-defined Object' FROM sys.filetable_system_defined_objects ORDER BY FileTable, 'System-defined Object';GONow try to map this created table in DataAccess.
Greetings,
Florian
Here is a complete sample. The sql script is similar to the one posted above. Please note that you need SQL-Server 2012 or above with enabled filestream-support on the instance-level. There are some screenshots in the sql-folder (in german, sorry ;)).
Thank you for the provided sample. We were able to successfully reproduce the issue in our test environment but we will need more time to investigate what is causing it. We will do our best to answer you as soon as possible.
Thank you for your understanding.
Regards,
Boris Georgiev
Telerik
Hi Boris,
Thanks for your investigations. Could you tell me about the status on this issue?
Basically I just need the following:
- non nullable BinaryStream-column support: If you insert/flush entities with a non-nullable BinaryStream-column (aka FileStream-column on SQL-Server), then the framework should insert 0x as a placeholder.
- proper support for SqlHierarchyId: I could do the workaround, but the querying isn't very comfortable and associations nearly impossible to do...
Regards,
Florian
I took over this ticket but need a bit more time for investigation. I will be able to continue working on this on monday, hoping that this is not to late for you.
Regards,
Thomas
Telerik
Hi Thomas
Thanks for helping me with this. I really appreciate a clean solution as my workarounds are dirty ;)
Regards,
Florian
Hi,
Any info about this issue?
Kind regards,
Igor
at the moment it looks like a problem in our implementation. There is a tiny chance I get it working tomorrow
by specifying a converter, but I'm not very optimistic on this. I will investigate this further and let you know about the outcome.
Regards,
Thomas
Telerik
looks like a new converter won't do it. Basic file stream usage seems ok, but file tables with their constraints aren't handled adequately. I will need to file a bug entry for this!
The only workaround that is worth mentioning is to use the ADO API to insert a FileTable object:
private static void InsertDocumentStore(Guid id, string title, byte[] content, bool isReadonly = false) { using (var connection = DatabaseSpecificTestBase.DataContext.Connection) { using (var command = connection.CreateCommand()) { command.CommandText = @"INSERT INTO [DocumentStore]([stream_id], [file_stream], [name], [path_locator], [creation_time], [last_write_time], [last_access_time], [is_directory], [is_offline], [is_hidden], [is_readonly], [is_archive], [is_system], [is_temporary])VALUES (@id, @content, @title, DEFAULT, GETDATE(), GETDATE(), GETDATE(), 0, 0, 0, @is_readonly, 0, 0, 0)"; StreamTestBase.AddParameter(command, "@id", DbType.Guid, id); StreamTestBase.AddParameter(command, "@title", DbType.String, title); StreamTestBase.AddParameter(command, "@content", DbType.Binary, content); StreamTestBase.AddParameter(command, "@is_readonly", DbType.Boolean, isReadonly); command.ExecuteNonQuery(); } } }Thanks for reporting this issue with us, hope we can finally fix it in a future version.
Regards,
Thomas
Telerik
Hi Thomas,
Thanks for your workaround. I am still going to wait for the bugfix-release. Do you have any clues about the roadmap on this?
Best regards,
Florian
I am sorry, but I cannot give you any timeline when the required fix will be available.
My suggestion is to try the work around and if it works potentially grow it into a Stored Procedure.
If you are unable to resolve the issue with the provided suggestion do not hesitate to contact us.
Regards,
Viktor Zhivkov
Telerik